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