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