Mercurial > flash_v2
annotate packages/kernel/current/include/mboxt.inl @ 143:6b5f480c6929 ecos-sw-2000-12-08
Merge from eCos master repository on 2000-12-08-02:09:36-GMT
| author | jlarmour |
|---|---|
| date | Fri, 08 Dec 2000 03:30:06 +0000 |
| parents | 6ed91473a1cd |
| children | e0c0827131d1 |
| rev | line source |
|---|---|
| 0 | 1 #ifndef CYGONCE_KERNEL_MBOXT_INL |
| 2 #define CYGONCE_KERNEL_MBOXT_INL | |
| 3 //========================================================================== | |
| 4 // | |
| 2 | 5 // mboxt.inl |
| 0 | 6 // |
| 2 | 7 // Mboxt mbox template class implementation |
| 0 | 8 // |
| 9 //========================================================================== | |
| 10 //####COPYRIGHTBEGIN#### | |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
11 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
12 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
13 // The contents of this file are subject to the Red Hat eCos Public License |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
14 // Version 1.1 (the "License"); you may not use this file except in |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
15 // compliance with the License. You may obtain a copy of the License at |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
16 // http://www.redhat.com/ |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
17 // |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
18 // Software distributed under the License is distributed on an "AS IS" |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
19 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
20 // License for the specific language governing rights and limitations under |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
21 // the License. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
22 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
23 // The Original Code is eCos - Embedded Configurable Operating System, |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
24 // released September 30, 1998. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
25 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
26 // The Initial Developer of the Original Code is Red Hat. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
27 // Portions created by Red Hat are |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
28 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
29 // All Rights Reserved. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
30 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
31 // |
| 0 | 32 //####COPYRIGHTEND#### |
| 33 //========================================================================== | |
| 34 //#####DESCRIPTIONBEGIN#### | |
| 35 // | |
| 2 | 36 // Author(s): hmt |
| 37 // Contributors: hmt | |
| 38 // Date: 1998-02-10 | |
| 39 // Purpose: Mboxt template implementation | |
| 40 // Description: This file contains the implementations of the mboxt | |
| 0 | 41 // template classes. |
| 42 // | |
| 43 //####DESCRIPTIONEND#### | |
| 44 // | |
| 45 //========================================================================== | |
| 46 | |
| 47 #include <pkgconf/kernel.h> | |
| 48 | |
| 49 #include <cyg/kernel/ktypes.h> // base kernel types | |
| 50 #include <cyg/infra/cyg_trac.h> // tracing macros | |
| 51 #include <cyg/infra/cyg_ass.h> // assertion macros | |
| 52 #include <cyg/kernel/instrmnt.h> // instrumentation | |
| 53 | |
| 54 #include <cyg/kernel/mboxt.hxx> // our header | |
| 55 | |
| 56 #include <cyg/kernel/thread.inl> // thread inlines | |
| 57 #include <cyg/kernel/sched.inl> // scheduler inlines | |
| 58 #include <cyg/kernel/clock.inl> // clock inlines | |
| 59 | |
| 60 // ------------------------------------------------------------------------- | |
| 61 // inline function for awakening waiting threads | |
| 62 | |
| 63 template <class T, cyg_count32 QUEUE_SIZE> | |
| 64 inline void | |
| 65 Cyg_Mboxt<T,QUEUE_SIZE>::wakeup_waiter( Cyg_ThreadQueue &q ) | |
| 66 { | |
| 67 if( !q.empty() ) { | |
| 68 // The queue is non-empty, so grab the next thread and wake it up. | |
| 69 Cyg_Thread *thread = q.dequeue(); | |
| 70 | |
| 71 CYG_ASSERTCLASS( thread, "Bad thread pointer"); | |
| 72 | |
| 73 thread->set_wake_reason( Cyg_Thread::DONE ); | |
| 74 thread->wake(); | |
| 75 CYG_INSTRUMENT_MBOXT(WAKE, this, thread); | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 // ------------------------------------------------------------------------- | |
| 80 // Constructor | |
| 81 | |
| 82 template <class T, cyg_count32 QUEUE_SIZE> | |
| 83 Cyg_Mboxt<T,QUEUE_SIZE>::Cyg_Mboxt() | |
| 84 { | |
| 85 CYG_REPORT_FUNCTION(); | |
| 86 base = 0; | |
| 87 count = 0; | |
| 88 } | |
| 89 | |
| 90 // ------------------------------------------------------------------------- | |
| 91 // Destructor | |
| 92 | |
| 93 template <class T, cyg_count32 QUEUE_SIZE> | |
| 94 Cyg_Mboxt<T,QUEUE_SIZE>::~Cyg_Mboxt() | |
| 95 { | |
| 96 CYG_REPORT_FUNCTION(); | |
| 97 CYG_ASSERT( 0 == count, "Deleting mboxt with messages"); | |
| 98 CYG_ASSERT( get_threadq.empty(), "Deleting mboxt with threads waiting to get"); | |
| 99 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 100 CYG_ASSERT( put_threadq.empty(), "Deleting mboxt with threads waiting to put"); | |
| 101 #endif | |
| 102 } | |
| 103 | |
| 104 // ------------------------------------------------------------------------- | |
| 105 // debugging/assert function | |
| 106 | |
| 107 #ifdef CYGDBG_USE_ASSERTS | |
| 108 | |
| 109 template <class T, cyg_count32 QUEUE_SIZE> | |
| 110 cyg_bool | |
| 2 | 111 Cyg_Mboxt<T,QUEUE_SIZE>::check_this(cyg_assert_class_zeal zeal) const |
| 0 | 112 { |
| 113 CYG_REPORT_FUNCTION(); | |
| 114 | |
| 115 if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() ) | |
| 116 // then the whole thing is invalid, and we know it. | |
| 117 // so return OK, since this check should NOT make an error. | |
| 118 return true; | |
| 119 | |
| 120 // check that we have a non-NULL pointer first | |
| 121 if( this == NULL ) return false; | |
| 122 | |
| 123 #if 0 // thread queues do not have checking funcs. | |
| 124 if ( ! get_threadq.check_this( zeal ) ) return false; | |
| 125 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 126 if ( ! put_threadq.check_this( zeal ) ) return false; | |
| 127 #endif | |
| 128 #endif | |
| 129 | |
| 130 switch( zeal ) | |
| 131 { | |
| 132 case cyg_system_test: | |
| 133 case cyg_extreme: | |
| 134 case cyg_thorough: | |
| 135 case cyg_quick: | |
| 136 case cyg_trivial: | |
| 137 // plenty of scope for fencepost problems here | |
| 138 if ( size < count ) return false; | |
| 139 if ( size <= base ) return false; | |
| 140 if ( 0 > count ) return false; | |
| 141 if ( 0 > base ) return false; | |
| 142 | |
| 143 // there was initially a test of the form | |
| 144 // (0 < count && count < size) && ! threadqueue.empty() | |
| 145 // here - ie. there should only be people waiting if the Q is full | |
| 146 // or empty. This is bogus, anyone else might run between a waiter | |
| 147 // being awoken, so there can be a 2nd waiter in the Q and a free | |
| 148 // slot (say) simultaneously. | |
| 149 | |
| 150 // Further, we need 2 queues; imagine a 10-slot itemqueue with 25 | |
| 151 // attempts to put to it, so 15 sleep. 10 other threads get, | |
| 152 // awakening 10 of the 15 put-sleepers. Another one gets, and | |
| 153 // can't because there is no data there _yet_; it sleeps, and the | |
| 154 // 10 awakened threads cycle through the run queue, each putting, | |
| 155 // the first awakens the get-sleeper, which in turn awakens a | |
| 156 // further put-sleeper. | |
| 157 | |
| 158 // This requirement for 2 queue only holds if Ngetters > 2 * Nslots | |
| 159 // or Nputters > 2 * Nslots; if these are both false, one queue | |
| 160 // will suffice. This could be an optimisation for the future - | |
| 161 // wow, 4 bytes. | |
| 162 | |
| 163 case cyg_none: | |
| 164 default: | |
| 165 break; | |
| 166 }; | |
| 167 | |
| 168 return true; | |
| 169 } | |
| 170 | |
| 171 #endif | |
| 172 | |
| 173 | |
| 174 // ------------------------------------------------------------------------- | |
| 175 // From here downwards, these are the major functions of the template; if | |
| 176 // being genuinely used as a template they should probably not be inlined. | |
| 177 // If being used to construct a specific class, with explicit functions, | |
| 178 // then they should be. This is controlled by: | |
| 179 | |
| 180 #ifdef CYGIMP_MBOXT_INLINE | |
| 181 #define CYG_MBOXT_INLINE inline | |
| 182 #else | |
| 183 #define CYG_MBOXT_INLINE | |
| 184 #endif | |
| 185 | |
| 186 // ------------------------------------------------------------------------- | |
| 187 // Get an item, or wait for one to arrive | |
| 188 | |
| 189 template <class T, cyg_count32 QUEUE_SIZE> | |
| 190 CYG_MBOXT_INLINE cyg_bool | |
| 191 Cyg_Mboxt<T,QUEUE_SIZE>::get( T &ritem ) | |
| 192 { | |
| 193 CYG_REPORT_FUNCTION(); | |
| 194 cyg_bool result = true; | |
| 195 | |
| 196 Cyg_Thread *self = Cyg_Thread::self(); | |
| 197 | |
| 198 // Prevent preemption | |
| 199 Cyg_Scheduler::lock(); | |
| 200 | |
| 201 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 202 | |
| 203 CYG_INSTRUMENT_MBOXT(GET, this, count); | |
| 204 | |
| 205 // Loop while the mboxt is empty, sleeping each time around | |
| 206 // the loop. This copes with the possibility of a higher priority | |
| 207 // thread grabbing the message between the wakeup in unlock() and | |
| 208 // this thread actually starting. | |
| 209 | |
| 210 while( result && (0 == count) ) { | |
| 211 self->set_sleep_reason( Cyg_Thread::WAIT ); | |
| 212 self->sleep(); | |
| 213 get_threadq.enqueue( self ); | |
| 214 | |
| 215 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
| 216 | |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
217 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
218 Cyg_Scheduler::reschedule(); |
| 0 | 219 |
| 220 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 221 | |
| 222 switch( self->get_wake_reason() ) | |
| 223 { | |
| 224 case Cyg_Thread::DESTRUCT: | |
| 225 case Cyg_Thread::BREAK: | |
| 226 result = false; | |
| 227 break; | |
| 228 | |
| 229 case Cyg_Thread::EXIT: | |
| 230 self->exit(); | |
| 231 break; | |
| 232 | |
| 233 default: | |
| 234 break; | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 if ( result ) { | |
| 239 CYG_INSTRUMENT_MBOXT(GOT, this, count); | |
| 240 | |
| 241 ritem = itemqueue[ (count--, base++) ]; | |
| 242 CYG_ASSERT( 0 <= count, "Count went -ve" ); | |
| 243 CYG_ASSERT( size >= base, "Base overflow" ); | |
| 244 | |
| 245 if ( size <= base ) | |
| 246 base = 0; | |
| 247 | |
| 248 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 249 wakeup_waiter( put_threadq ); | |
| 250 #endif | |
| 251 } | |
| 252 | |
| 253 // Unlock the scheduler and maybe switch threads | |
| 254 Cyg_Scheduler::unlock(); | |
| 255 | |
| 256 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 257 CYG_REPORT_RETVAL( result ); | |
| 258 return result; | |
| 259 } | |
| 260 | |
| 261 | |
| 262 // ------------------------------------------------------------------------- | |
| 263 // Try to get an item with an absolute timeout and return success. | |
| 264 | |
| 265 #ifdef CYGFUN_KERNEL_THREADS_TIMER | |
| 266 template <class T, cyg_count32 QUEUE_SIZE> | |
| 267 CYG_MBOXT_INLINE cyg_bool | |
| 268 Cyg_Mboxt<T,QUEUE_SIZE>::get( T &ritem, cyg_tick_count abs_timeout ) | |
| 269 { | |
| 270 CYG_REPORT_FUNCTION(); | |
| 271 cyg_bool result = true; | |
| 272 | |
| 273 Cyg_Thread *self = Cyg_Thread::self(); | |
| 274 | |
| 275 // Prevent preemption | |
| 276 Cyg_Scheduler::lock(); | |
| 277 | |
| 278 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 279 | |
| 280 CYG_INSTRUMENT_MBOXT(GET, this, count); | |
| 281 | |
| 282 // Set the timer _once_ outside the loop. | |
| 283 self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT ); | |
| 284 | |
| 285 // If the timeout is in the past, the wake reason will have been | |
| 286 // set to something other than NONE already. Set the result false | |
| 287 // to force an immediate return. | |
| 288 | |
| 289 if( self->get_wake_reason() != Cyg_Thread::NONE ) | |
| 290 result = false; | |
| 291 | |
| 292 // Loop while the mboxt is empty, sleeping each time around the loop. | |
| 293 // This copes with the possibility of a higher priority thread grabbing | |
| 294 // the message between the wakeup in put()&c and this thread actually | |
| 295 // starting. | |
| 296 while ( result && (0 == count) ) { | |
| 297 // must reset the sleep reason every time | |
| 298 self->set_sleep_reason( Cyg_Thread::TIMEOUT ); | |
| 299 self->sleep(); | |
| 300 get_threadq.enqueue( self ); | |
| 301 | |
| 302 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
| 303 | |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
304 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
305 Cyg_Scheduler::reschedule(); |
| 0 | 306 |
| 307 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 308 | |
| 309 switch( self->get_wake_reason() ) | |
| 310 { | |
| 311 case Cyg_Thread::TIMEOUT: | |
| 312 result = false; | |
| 313 CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count); | |
| 314 break; | |
| 315 | |
| 316 case Cyg_Thread::DESTRUCT: | |
| 317 case Cyg_Thread::BREAK: | |
| 318 result = false; | |
| 319 break; | |
| 320 | |
| 321 case Cyg_Thread::EXIT: | |
| 322 self->exit(); | |
| 323 break; | |
| 324 | |
| 325 default: | |
| 326 break; | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 // clear the timer; if it actually fired, no worries. | |
| 331 self->clear_timer(); | |
| 332 | |
| 333 if ( result ) { | |
| 334 | |
| 335 CYG_INSTRUMENT_MBOXT(GOT, this, count); | |
| 336 | |
| 337 ritem = itemqueue[ (count--, base++) ]; | |
| 338 CYG_ASSERT( 0 <= count, "Count went -ve" ); | |
| 339 CYG_ASSERT( size >= base, "Base overflow" ); | |
| 340 | |
| 341 if ( size <= base ) | |
| 342 base = 0; | |
| 343 | |
| 344 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 345 wakeup_waiter( put_threadq ); | |
| 346 #endif | |
| 347 } | |
| 348 | |
| 349 // Unlock the scheduler and maybe switch threads | |
| 350 Cyg_Scheduler::unlock(); | |
| 351 | |
| 352 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 353 CYG_REPORT_RETVAL( result ); | |
| 354 return result; | |
| 355 } | |
| 356 #endif // CYGFUN_KERNEL_THREADS_TIMER | |
| 357 | |
| 358 // ------------------------------------------------------------------------- | |
| 359 // Try to get an item and return success. | |
| 360 | |
| 361 template <class T, cyg_count32 QUEUE_SIZE> | |
| 362 CYG_MBOXT_INLINE cyg_bool | |
| 363 Cyg_Mboxt<T,QUEUE_SIZE>::tryget( T &ritem ) | |
| 364 { | |
| 365 CYG_REPORT_FUNCTION(); | |
| 366 | |
| 367 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 368 | |
| 369 // Prevent preemption | |
| 370 Cyg_Scheduler::lock(); | |
| 371 | |
| 372 CYG_INSTRUMENT_MBOXT(TRY, this, count); | |
| 373 | |
| 374 cyg_bool result = ( 0 < count ); | |
| 375 // If the mboxt is not empty, grab an item and return it. | |
| 376 if ( result ) { | |
| 377 ritem = itemqueue[ (count--, base++) ]; | |
| 378 CYG_ASSERT( 0 <= count, "Count went -ve" ); | |
| 379 CYG_ASSERT( size >= base, "Base overflow" ); | |
| 380 if ( size <= base ) | |
| 381 base = 0; | |
| 382 | |
| 383 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 384 wakeup_waiter( put_threadq ); | |
| 385 #endif | |
| 386 } | |
| 387 | |
| 388 // Unlock the scheduler and maybe switch threads | |
| 389 Cyg_Scheduler::unlock(); | |
| 390 | |
| 391 return result; | |
| 392 } | |
| 393 | |
| 394 // ------------------------------------------------------------------------- | |
| 395 // get next item without removing it | |
| 396 template <class T, cyg_count32 QUEUE_SIZE> | |
| 397 CYG_MBOXT_INLINE cyg_bool | |
| 398 Cyg_Mboxt<T,QUEUE_SIZE>::peek_item( T &ritem ) | |
| 399 { | |
| 400 CYG_REPORT_FUNCTION(); | |
| 401 | |
| 402 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 403 | |
| 404 // Prevent preemption | |
| 405 Cyg_Scheduler::lock(); | |
| 406 | |
| 407 CYG_INSTRUMENT_MBOXT(TRY, this, count); | |
| 408 | |
| 409 cyg_bool result = ( 0 < count ); | |
| 410 // If the mboxt is not empty, grab an item and return it. | |
| 411 if ( result ) | |
| 412 ritem = itemqueue[ base ]; | |
| 413 | |
| 414 // Unlock the scheduler and maybe switch threads | |
| 415 Cyg_Scheduler::unlock(); | |
| 416 | |
| 417 return result; | |
| 418 } | |
| 419 | |
| 420 // ------------------------------------------------------------------------- | |
| 421 // Put an item in the queue; wait if full. | |
| 422 | |
| 423 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 424 template <class T, cyg_count32 QUEUE_SIZE> | |
| 425 CYG_MBOXT_INLINE cyg_bool | |
| 426 Cyg_Mboxt<T,QUEUE_SIZE>::put( const T item ) | |
| 427 { | |
| 428 CYG_REPORT_FUNCTION(); | |
| 429 cyg_bool result = true; | |
| 430 | |
| 431 Cyg_Thread *self = Cyg_Thread::self(); | |
| 432 | |
| 433 // Prevent preemption | |
| 434 Cyg_Scheduler::lock(); | |
| 435 | |
| 436 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 437 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 438 | |
| 439 while ( result && (size == count) ) { | |
| 440 self->set_sleep_reason( Cyg_Thread::WAIT ); | |
| 441 self->sleep(); | |
| 442 put_threadq.enqueue( self ); | |
| 443 | |
| 444 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
445 |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
446 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
447 Cyg_Scheduler::reschedule(); |
| 0 | 448 |
| 449 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 450 | |
| 451 switch( self->get_wake_reason() ) | |
| 452 { | |
| 453 case Cyg_Thread::DESTRUCT: | |
| 454 case Cyg_Thread::BREAK: | |
| 455 result = false; | |
| 456 break; | |
| 457 | |
| 458 case Cyg_Thread::EXIT: | |
| 459 self->exit(); | |
| 460 break; | |
| 461 | |
| 462 default: | |
| 463 break; | |
| 464 } | |
| 465 } | |
| 466 | |
| 467 if ( result ) { | |
| 468 cyg_count32 in = base + (count++); | |
| 469 if ( size <= in ) | |
| 470 in -= size; | |
| 471 | |
| 472 CYG_ASSERT( size > in, "in overflow" ); | |
| 473 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 474 CYG_ASSERT( size >= count, "count overflow" ); | |
| 475 | |
| 476 itemqueue[ in ] = item; | |
| 477 | |
| 478 wakeup_waiter( get_threadq ); | |
| 479 } | |
| 480 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 481 | |
| 482 // Unlock the scheduler and maybe switch threads | |
| 483 Cyg_Scheduler::unlock(); | |
| 484 CYG_REPORT_RETVAL( result ); | |
| 485 return result; | |
| 486 } | |
| 487 | |
| 488 // ------------------------------------------------------------------------- | |
| 489 // Put an item in the queue; wait if full, with an absolute timeout; | |
| 490 // return success. | |
| 491 | |
| 492 #ifdef CYGFUN_KERNEL_THREADS_TIMER | |
| 493 template <class T, cyg_count32 QUEUE_SIZE> | |
| 494 CYG_MBOXT_INLINE cyg_bool | |
| 495 Cyg_Mboxt<T,QUEUE_SIZE>::put( const T item, cyg_tick_count abs_timeout ) | |
| 496 { | |
| 497 CYG_REPORT_FUNCTION(); | |
| 498 cyg_bool result = true; | |
| 499 | |
| 500 Cyg_Thread *self = Cyg_Thread::self(); | |
| 501 | |
| 502 // Prevent preemption | |
| 503 Cyg_Scheduler::lock(); | |
| 504 | |
| 505 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 506 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 507 | |
| 508 // Set the timer _once_ outside the loop. | |
| 509 self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT ); | |
| 510 | |
| 511 // If the timeout is in the past, the wake reason will have been | |
| 512 // set to something other than NONE already. Set the result false | |
| 513 // to force an immediate return. | |
| 514 | |
| 515 if( self->get_wake_reason() != Cyg_Thread::NONE ) | |
| 516 result = false; | |
| 517 | |
| 518 // Loop while the mboxt is full, sleeping each time around the loop. | |
| 519 // This copes with the possibility of a higher priority thread filling | |
| 520 // the empty slot between the wakeup in get()&c and this thread | |
| 521 // actually starting. | |
| 522 while ( result && (size == count) ) { | |
| 523 // must reset the sleep reason every time | |
| 524 self->set_sleep_reason( Cyg_Thread::TIMEOUT ); | |
| 525 self->sleep(); | |
| 526 put_threadq.enqueue( self ); | |
| 527 | |
| 528 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
| 529 | |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
530 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
531 Cyg_Scheduler::reschedule(); |
| 0 | 532 |
| 533 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 534 | |
| 535 switch( self->get_wake_reason() ) | |
| 536 { | |
| 537 case Cyg_Thread::TIMEOUT: | |
| 538 result = false; | |
| 539 CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count); | |
| 540 break; | |
| 541 | |
| 542 case Cyg_Thread::DESTRUCT: | |
| 543 case Cyg_Thread::BREAK: | |
| 544 result = false; | |
| 545 break; | |
| 546 | |
| 547 case Cyg_Thread::EXIT: | |
| 548 self->exit(); | |
| 549 break; | |
| 550 | |
| 551 default: | |
| 552 break; | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 // clear the timer; if it actually fired, no worries. | |
| 557 self->clear_timer(); | |
| 558 | |
| 559 if ( result ) { | |
| 560 cyg_count32 in = base + (count++); | |
| 561 if ( size <= in ) | |
| 562 in -= size; | |
| 563 | |
| 564 CYG_ASSERT( size > in, "in overflow" ); | |
| 565 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 566 CYG_ASSERT( size >= count, "count overflow" ); | |
| 567 | |
| 568 itemqueue[ in ] = item; | |
| 569 | |
| 570 wakeup_waiter( get_threadq ); | |
| 571 } | |
| 572 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 573 | |
| 574 // Unlock the scheduler and maybe switch threads | |
| 575 Cyg_Scheduler::unlock(); | |
| 576 CYG_REPORT_RETVAL( result ); | |
| 577 return result; | |
| 578 } | |
| 579 #endif // CYGFUN_KERNEL_THREADS_TIMER | |
| 580 #endif // CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 581 | |
| 582 // ------------------------------------------------------------------------- | |
| 583 // Try to put an item in the queue and return success; queue may be full. | |
| 584 | |
| 585 template <class T, cyg_count32 QUEUE_SIZE> | |
| 586 CYG_MBOXT_INLINE cyg_bool | |
| 587 Cyg_Mboxt<T,QUEUE_SIZE>::tryput( const T item ) | |
| 588 { | |
| 589 CYG_REPORT_FUNCTION(); | |
| 590 | |
| 591 // Prevent preemption | |
| 592 Cyg_Scheduler::lock(); | |
| 593 | |
| 594 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 595 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 596 | |
| 597 if ( size == count ) { | |
| 598 Cyg_Scheduler::unlock(); // unlock, maybe switch threads | |
| 599 return false; // the mboxt is full | |
| 600 } | |
| 601 | |
| 602 cyg_count32 in = base + (count++); | |
| 603 if ( size <= in ) | |
| 604 in -= size; | |
| 605 | |
| 606 CYG_ASSERT( size > in, "in overflow" ); | |
| 607 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 608 CYG_ASSERT( size >= count, "count overflow" ); | |
| 609 | |
| 610 itemqueue[ in ] = item; | |
| 611 | |
| 612 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 613 | |
| 614 wakeup_waiter( get_threadq ); | |
| 615 | |
| 616 // Unlock the scheduler and maybe switch threads | |
| 617 Cyg_Scheduler::unlock(); | |
| 618 | |
| 619 return true; | |
| 620 } | |
| 621 | |
| 622 | |
| 623 // ------------------------------------------------------------------------- | |
| 624 #endif // ifndef CYGONCE_KERNEL_MBOXT_INL | |
| 625 // EOF mboxt.inl |
