Mercurial > ecos
annotate packages/kernel/current/include/mboxt.inl @ 2729:74dbf4c3f2e1 after-copyright-change-20090129
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
| author | jlarmour |
|---|---|
| date | Thu, 29 Jan 2009 17:47:46 +0000 |
| parents | 4be03fe7814d |
| children |
| 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 //========================================================================== | |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
10 // ####ECOSGPLCOPYRIGHTBEGIN#### |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
11 // ------------------------------------------- |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
12 // This file is part of eCos, the Embedded Configurable Operating System. |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
115
diff
changeset
|
14 // |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
15 // eCos is free software; you can redistribute it and/or modify it under |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
16 // the terms of the GNU General Public License as published by the Free |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
17 // Software Foundation; either version 2 or (at your option) any later |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
18 // version. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
115
diff
changeset
|
19 // |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
20 // eCos is distributed in the hope that it will be useful, but WITHOUT |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
21 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
22 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
23 // for more details. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
115
diff
changeset
|
24 // |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
25 // You should have received a copy of the GNU General Public License |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
26 // along with eCos; if not, write to the Free Software Foundation, Inc., |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
27 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
115
diff
changeset
|
28 // |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
29 // As a special exception, if other files instantiate templates or use |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
30 // macros or inline functions from this file, or you compile this file |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
31 // and link it with other works to produce a work based on this file, |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
32 // this file does not by itself cause the resulting work to be covered by |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
33 // the GNU General Public License. However the source code for this file |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
34 // must still be made available in accordance with section (3) of the GNU |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
35 // General Public License v2. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
115
diff
changeset
|
36 // |
|
2729
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
37 // This exception does not invalidate any other reasons why a work based |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
38 // on this file might be covered by the GNU General Public License. |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
39 // ------------------------------------------- |
|
74dbf4c3f2e1
Update all copyright banners to reflect FSF ownership; fix and improve licence text.
jlarmour
parents:
2310
diff
changeset
|
40 // ####ECOSGPLCOPYRIGHTEND#### |
| 0 | 41 //========================================================================== |
| 42 //#####DESCRIPTIONBEGIN#### | |
| 43 // | |
| 2 | 44 // Author(s): hmt |
| 45 // Contributors: hmt | |
| 46 // Date: 1998-02-10 | |
| 47 // Purpose: Mboxt template implementation | |
| 48 // Description: This file contains the implementations of the mboxt | |
| 0 | 49 // template classes. |
| 50 // | |
| 51 //####DESCRIPTIONEND#### | |
| 52 // | |
| 53 //========================================================================== | |
| 54 | |
| 55 #include <pkgconf/kernel.h> | |
| 56 | |
| 57 #include <cyg/kernel/ktypes.h> // base kernel types | |
| 58 #include <cyg/infra/cyg_trac.h> // tracing macros | |
| 59 #include <cyg/infra/cyg_ass.h> // assertion macros | |
| 60 #include <cyg/kernel/instrmnt.h> // instrumentation | |
| 61 | |
| 62 #include <cyg/kernel/mboxt.hxx> // our header | |
| 63 | |
| 64 #include <cyg/kernel/thread.inl> // thread inlines | |
| 65 #include <cyg/kernel/sched.inl> // scheduler inlines | |
| 66 #include <cyg/kernel/clock.inl> // clock inlines | |
| 67 | |
| 68 // ------------------------------------------------------------------------- | |
| 69 // inline function for awakening waiting threads | |
| 70 | |
| 71 template <class T, cyg_count32 QUEUE_SIZE> | |
| 72 inline void | |
| 73 Cyg_Mboxt<T,QUEUE_SIZE>::wakeup_waiter( Cyg_ThreadQueue &q ) | |
| 74 { | |
| 75 if( !q.empty() ) { | |
| 76 // The queue is non-empty, so grab the next thread and wake it up. | |
| 77 Cyg_Thread *thread = q.dequeue(); | |
| 78 | |
| 79 CYG_ASSERTCLASS( thread, "Bad thread pointer"); | |
| 80 | |
| 81 thread->set_wake_reason( Cyg_Thread::DONE ); | |
| 82 thread->wake(); | |
| 83 CYG_INSTRUMENT_MBOXT(WAKE, this, thread); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 // ------------------------------------------------------------------------- | |
| 88 // Constructor | |
| 89 | |
| 90 template <class T, cyg_count32 QUEUE_SIZE> | |
| 91 Cyg_Mboxt<T,QUEUE_SIZE>::Cyg_Mboxt() | |
| 92 { | |
| 93 CYG_REPORT_FUNCTION(); | |
| 94 base = 0; | |
| 95 count = 0; | |
| 96 } | |
| 97 | |
| 98 // ------------------------------------------------------------------------- | |
| 99 // Destructor | |
| 100 | |
| 101 template <class T, cyg_count32 QUEUE_SIZE> | |
| 102 Cyg_Mboxt<T,QUEUE_SIZE>::~Cyg_Mboxt() | |
| 103 { | |
| 104 CYG_REPORT_FUNCTION(); | |
| 105 CYG_ASSERT( 0 == count, "Deleting mboxt with messages"); | |
| 106 CYG_ASSERT( get_threadq.empty(), "Deleting mboxt with threads waiting to get"); | |
| 107 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 108 CYG_ASSERT( put_threadq.empty(), "Deleting mboxt with threads waiting to put"); | |
| 109 #endif | |
| 110 } | |
| 111 | |
| 112 // ------------------------------------------------------------------------- | |
| 113 // debugging/assert function | |
| 114 | |
| 115 #ifdef CYGDBG_USE_ASSERTS | |
| 116 | |
| 117 template <class T, cyg_count32 QUEUE_SIZE> | |
| 118 cyg_bool | |
| 2 | 119 Cyg_Mboxt<T,QUEUE_SIZE>::check_this(cyg_assert_class_zeal zeal) const |
| 0 | 120 { |
| 121 CYG_REPORT_FUNCTION(); | |
| 122 | |
| 123 if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() ) | |
| 124 // then the whole thing is invalid, and we know it. | |
| 125 // so return OK, since this check should NOT make an error. | |
| 126 return true; | |
| 127 | |
| 128 // check that we have a non-NULL pointer first | |
| 129 if( this == NULL ) return false; | |
| 130 | |
| 131 #if 0 // thread queues do not have checking funcs. | |
| 132 if ( ! get_threadq.check_this( zeal ) ) return false; | |
| 133 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 134 if ( ! put_threadq.check_this( zeal ) ) return false; | |
| 135 #endif | |
| 136 #endif | |
| 137 | |
| 138 switch( zeal ) | |
| 139 { | |
| 140 case cyg_system_test: | |
| 141 case cyg_extreme: | |
| 142 case cyg_thorough: | |
| 143 case cyg_quick: | |
| 144 case cyg_trivial: | |
| 145 // plenty of scope for fencepost problems here | |
| 146 if ( size < count ) return false; | |
| 147 if ( size <= base ) return false; | |
| 148 if ( 0 > count ) return false; | |
| 149 if ( 0 > base ) return false; | |
| 150 | |
| 151 // there was initially a test of the form | |
| 152 // (0 < count && count < size) && ! threadqueue.empty() | |
| 153 // here - ie. there should only be people waiting if the Q is full | |
| 154 // or empty. This is bogus, anyone else might run between a waiter | |
| 155 // being awoken, so there can be a 2nd waiter in the Q and a free | |
| 156 // slot (say) simultaneously. | |
| 157 | |
| 158 // Further, we need 2 queues; imagine a 10-slot itemqueue with 25 | |
| 159 // attempts to put to it, so 15 sleep. 10 other threads get, | |
| 160 // awakening 10 of the 15 put-sleepers. Another one gets, and | |
| 161 // can't because there is no data there _yet_; it sleeps, and the | |
| 162 // 10 awakened threads cycle through the run queue, each putting, | |
| 163 // the first awakens the get-sleeper, which in turn awakens a | |
| 164 // further put-sleeper. | |
| 165 | |
| 166 // This requirement for 2 queue only holds if Ngetters > 2 * Nslots | |
| 167 // or Nputters > 2 * Nslots; if these are both false, one queue | |
| 168 // will suffice. This could be an optimisation for the future - | |
| 169 // wow, 4 bytes. | |
| 170 | |
| 171 case cyg_none: | |
| 172 default: | |
| 173 break; | |
| 174 }; | |
| 175 | |
| 176 return true; | |
| 177 } | |
| 178 | |
| 179 #endif | |
| 180 | |
| 181 | |
| 182 // ------------------------------------------------------------------------- | |
| 183 // From here downwards, these are the major functions of the template; if | |
| 184 // being genuinely used as a template they should probably not be inlined. | |
| 185 // If being used to construct a specific class, with explicit functions, | |
| 186 // then they should be. This is controlled by: | |
| 187 | |
| 188 #ifdef CYGIMP_MBOXT_INLINE | |
| 189 #define CYG_MBOXT_INLINE inline | |
| 190 #else | |
| 191 #define CYG_MBOXT_INLINE | |
| 192 #endif | |
| 193 | |
| 194 // ------------------------------------------------------------------------- | |
| 195 // Get an item, or wait for one to arrive | |
| 196 | |
| 197 template <class T, cyg_count32 QUEUE_SIZE> | |
| 198 CYG_MBOXT_INLINE cyg_bool | |
| 199 Cyg_Mboxt<T,QUEUE_SIZE>::get( T &ritem ) | |
| 200 { | |
| 201 CYG_REPORT_FUNCTION(); | |
| 202 cyg_bool result = true; | |
| 203 | |
| 204 Cyg_Thread *self = Cyg_Thread::self(); | |
| 205 | |
| 206 // Prevent preemption | |
| 207 Cyg_Scheduler::lock(); | |
| 208 | |
| 209 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 210 | |
| 211 CYG_INSTRUMENT_MBOXT(GET, this, count); | |
| 212 | |
| 213 // Loop while the mboxt is empty, sleeping each time around | |
| 214 // the loop. This copes with the possibility of a higher priority | |
| 215 // thread grabbing the message between the wakeup in unlock() and | |
| 216 // this thread actually starting. | |
| 217 | |
| 218 while( result && (0 == count) ) { | |
| 219 self->set_sleep_reason( Cyg_Thread::WAIT ); | |
| 220 self->sleep(); | |
| 221 get_threadq.enqueue( self ); | |
| 222 | |
| 223 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
| 224 | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
225 CYG_ASSERTCLASS( this, "Bad this pointer"); |
|
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
226 |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
227 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
228 Cyg_Scheduler::reschedule(); |
| 0 | 229 |
| 230 switch( self->get_wake_reason() ) | |
| 231 { | |
| 232 case Cyg_Thread::DESTRUCT: | |
| 233 case Cyg_Thread::BREAK: | |
| 234 result = false; | |
| 235 break; | |
| 236 | |
| 237 case Cyg_Thread::EXIT: | |
| 238 self->exit(); | |
| 239 break; | |
| 240 | |
| 241 default: | |
| 242 break; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 if ( result ) { | |
| 247 CYG_INSTRUMENT_MBOXT(GOT, this, count); | |
| 248 | |
| 249 ritem = itemqueue[ (count--, base++) ]; | |
| 250 CYG_ASSERT( 0 <= count, "Count went -ve" ); | |
| 251 CYG_ASSERT( size >= base, "Base overflow" ); | |
| 252 | |
| 253 if ( size <= base ) | |
| 254 base = 0; | |
| 255 | |
| 256 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 257 wakeup_waiter( put_threadq ); | |
| 258 #endif | |
| 259 } | |
| 260 | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
261 CYG_ASSERTCLASS( this, "Bad this pointer"); |
|
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
262 |
| 0 | 263 // Unlock the scheduler and maybe switch threads |
| 264 Cyg_Scheduler::unlock(); | |
| 265 | |
| 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); | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
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 | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
358 CYG_ASSERTCLASS( this, "Bad this pointer"); |
|
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
359 |
| 0 | 360 // Unlock the scheduler and maybe switch threads |
| 361 Cyg_Scheduler::unlock(); | |
| 362 | |
| 363 CYG_REPORT_RETVAL( result ); | |
| 364 return result; | |
| 365 } | |
| 366 #endif // CYGFUN_KERNEL_THREADS_TIMER | |
| 367 | |
| 368 // ------------------------------------------------------------------------- | |
| 369 // Try to get an item and return success. | |
| 370 | |
| 371 template <class T, cyg_count32 QUEUE_SIZE> | |
| 372 CYG_MBOXT_INLINE cyg_bool | |
| 373 Cyg_Mboxt<T,QUEUE_SIZE>::tryget( T &ritem ) | |
| 374 { | |
| 375 CYG_REPORT_FUNCTION(); | |
| 376 | |
| 377 // Prevent preemption | |
| 378 Cyg_Scheduler::lock(); | |
| 379 | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
380 CYG_ASSERTCLASS( this, "Bad this pointer"); |
|
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
381 |
| 0 | 382 CYG_INSTRUMENT_MBOXT(TRY, this, count); |
| 383 | |
| 384 cyg_bool result = ( 0 < count ); | |
| 385 // If the mboxt is not empty, grab an item and return it. | |
| 386 if ( result ) { | |
| 387 ritem = itemqueue[ (count--, base++) ]; | |
| 388 CYG_ASSERT( 0 <= count, "Count went -ve" ); | |
| 389 CYG_ASSERT( size >= base, "Base overflow" ); | |
| 390 if ( size <= base ) | |
| 391 base = 0; | |
| 392 | |
| 393 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 394 wakeup_waiter( put_threadq ); | |
| 395 #endif | |
| 396 } | |
| 397 | |
| 398 // Unlock the scheduler and maybe switch threads | |
| 399 Cyg_Scheduler::unlock(); | |
| 400 | |
| 401 return result; | |
| 402 } | |
| 403 | |
| 404 // ------------------------------------------------------------------------- | |
| 405 // get next item without removing it | |
| 406 template <class T, cyg_count32 QUEUE_SIZE> | |
| 407 CYG_MBOXT_INLINE cyg_bool | |
| 408 Cyg_Mboxt<T,QUEUE_SIZE>::peek_item( T &ritem ) | |
| 409 { | |
| 410 CYG_REPORT_FUNCTION(); | |
| 411 | |
| 412 // Prevent preemption | |
| 413 Cyg_Scheduler::lock(); | |
| 414 | |
|
2310
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
415 CYG_ASSERTCLASS( this, "Bad this pointer"); |
|
4be03fe7814d
* cdl/synch.cdl: Added CYGIMP_MBOX_USE_MBOXT_PLAIN option. This is
nickg
parents:
210
diff
changeset
|
416 |
| 0 | 417 CYG_INSTRUMENT_MBOXT(TRY, this, count); |
| 418 | |
| 419 cyg_bool result = ( 0 < count ); | |
| 420 // If the mboxt is not empty, grab an item and return it. | |
| 421 if ( result ) | |
| 422 ritem = itemqueue[ base ]; | |
| 423 | |
| 424 // Unlock the scheduler and maybe switch threads | |
| 425 Cyg_Scheduler::unlock(); | |
| 426 | |
| 427 return result; | |
| 428 } | |
| 429 | |
| 430 // ------------------------------------------------------------------------- | |
| 431 // Put an item in the queue; wait if full. | |
| 432 | |
| 433 #ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 434 template <class T, cyg_count32 QUEUE_SIZE> | |
| 435 CYG_MBOXT_INLINE cyg_bool | |
| 436 Cyg_Mboxt<T,QUEUE_SIZE>::put( const T item ) | |
| 437 { | |
| 438 CYG_REPORT_FUNCTION(); | |
| 439 cyg_bool result = true; | |
| 440 | |
| 441 Cyg_Thread *self = Cyg_Thread::self(); | |
| 442 | |
| 443 // Prevent preemption | |
| 444 Cyg_Scheduler::lock(); | |
| 445 | |
| 446 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 447 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 448 | |
| 449 while ( result && (size == count) ) { | |
| 450 self->set_sleep_reason( Cyg_Thread::WAIT ); | |
| 451 self->sleep(); | |
| 452 put_threadq.enqueue( self ); | |
| 453 | |
| 454 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
|
455 |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
456 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
457 Cyg_Scheduler::reschedule(); |
| 0 | 458 |
| 459 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 460 | |
| 461 switch( self->get_wake_reason() ) | |
| 462 { | |
| 463 case Cyg_Thread::DESTRUCT: | |
| 464 case Cyg_Thread::BREAK: | |
| 465 result = false; | |
| 466 break; | |
| 467 | |
| 468 case Cyg_Thread::EXIT: | |
| 469 self->exit(); | |
| 470 break; | |
| 471 | |
| 472 default: | |
| 473 break; | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 if ( result ) { | |
| 478 cyg_count32 in = base + (count++); | |
| 479 if ( size <= in ) | |
| 480 in -= size; | |
| 481 | |
| 482 CYG_ASSERT( size > in, "in overflow" ); | |
| 483 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 484 CYG_ASSERT( size >= count, "count overflow" ); | |
| 485 | |
| 486 itemqueue[ in ] = item; | |
| 487 | |
| 488 wakeup_waiter( get_threadq ); | |
| 489 } | |
| 490 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 491 | |
| 492 // Unlock the scheduler and maybe switch threads | |
| 493 Cyg_Scheduler::unlock(); | |
| 494 CYG_REPORT_RETVAL( result ); | |
| 495 return result; | |
| 496 } | |
| 497 | |
| 498 // ------------------------------------------------------------------------- | |
| 499 // Put an item in the queue; wait if full, with an absolute timeout; | |
| 500 // return success. | |
| 501 | |
| 502 #ifdef CYGFUN_KERNEL_THREADS_TIMER | |
| 503 template <class T, cyg_count32 QUEUE_SIZE> | |
| 504 CYG_MBOXT_INLINE cyg_bool | |
| 505 Cyg_Mboxt<T,QUEUE_SIZE>::put( const T item, cyg_tick_count abs_timeout ) | |
| 506 { | |
| 507 CYG_REPORT_FUNCTION(); | |
| 508 cyg_bool result = true; | |
| 509 | |
| 510 Cyg_Thread *self = Cyg_Thread::self(); | |
| 511 | |
| 512 // Prevent preemption | |
| 513 Cyg_Scheduler::lock(); | |
| 514 | |
| 515 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 516 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 517 | |
| 518 // Set the timer _once_ outside the loop. | |
| 519 self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT ); | |
| 520 | |
| 521 // If the timeout is in the past, the wake reason will have been | |
| 522 // set to something other than NONE already. Set the result false | |
| 523 // to force an immediate return. | |
| 524 | |
| 525 if( self->get_wake_reason() != Cyg_Thread::NONE ) | |
| 526 result = false; | |
| 527 | |
| 528 // Loop while the mboxt is full, sleeping each time around the loop. | |
| 529 // This copes with the possibility of a higher priority thread filling | |
| 530 // the empty slot between the wakeup in get()&c and this thread | |
| 531 // actually starting. | |
| 532 while ( result && (size == count) ) { | |
| 533 // must reset the sleep reason every time | |
| 534 self->set_sleep_reason( Cyg_Thread::TIMEOUT ); | |
| 535 self->sleep(); | |
| 536 put_threadq.enqueue( self ); | |
| 537 | |
| 538 CYG_INSTRUMENT_MBOXT(WAIT, this, count); | |
| 539 | |
|
115
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
540 // Allow other threads to run |
|
6ed91473a1cd
Merge from eCos master repository on 2000-08-21-22:40:54-BST
jlarmour
parents:
66
diff
changeset
|
541 Cyg_Scheduler::reschedule(); |
| 0 | 542 |
| 543 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 544 | |
| 545 switch( self->get_wake_reason() ) | |
| 546 { | |
| 547 case Cyg_Thread::TIMEOUT: | |
| 548 result = false; | |
| 549 CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count); | |
| 550 break; | |
| 551 | |
| 552 case Cyg_Thread::DESTRUCT: | |
| 553 case Cyg_Thread::BREAK: | |
| 554 result = false; | |
| 555 break; | |
| 556 | |
| 557 case Cyg_Thread::EXIT: | |
| 558 self->exit(); | |
| 559 break; | |
| 560 | |
| 561 default: | |
| 562 break; | |
| 563 } | |
| 564 } | |
| 565 | |
| 566 // clear the timer; if it actually fired, no worries. | |
| 567 self->clear_timer(); | |
| 568 | |
| 569 if ( result ) { | |
| 570 cyg_count32 in = base + (count++); | |
| 571 if ( size <= in ) | |
| 572 in -= size; | |
| 573 | |
| 574 CYG_ASSERT( size > in, "in overflow" ); | |
| 575 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 576 CYG_ASSERT( size >= count, "count overflow" ); | |
| 577 | |
| 578 itemqueue[ in ] = item; | |
| 579 | |
| 580 wakeup_waiter( get_threadq ); | |
| 581 } | |
| 582 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 583 | |
| 584 // Unlock the scheduler and maybe switch threads | |
| 585 Cyg_Scheduler::unlock(); | |
| 586 CYG_REPORT_RETVAL( result ); | |
| 587 return result; | |
| 588 } | |
| 589 #endif // CYGFUN_KERNEL_THREADS_TIMER | |
| 590 #endif // CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT | |
| 591 | |
| 592 // ------------------------------------------------------------------------- | |
| 593 // Try to put an item in the queue and return success; queue may be full. | |
| 594 | |
| 595 template <class T, cyg_count32 QUEUE_SIZE> | |
| 596 CYG_MBOXT_INLINE cyg_bool | |
| 597 Cyg_Mboxt<T,QUEUE_SIZE>::tryput( const T item ) | |
| 598 { | |
| 599 CYG_REPORT_FUNCTION(); | |
| 600 | |
| 601 // Prevent preemption | |
| 602 Cyg_Scheduler::lock(); | |
| 603 | |
| 604 CYG_INSTRUMENT_MBOXT(PUT, this, count); | |
| 605 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 606 | |
| 607 if ( size == count ) { | |
| 608 Cyg_Scheduler::unlock(); // unlock, maybe switch threads | |
| 609 return false; // the mboxt is full | |
| 610 } | |
| 611 | |
| 612 cyg_count32 in = base + (count++); | |
| 613 if ( size <= in ) | |
| 614 in -= size; | |
| 615 | |
| 616 CYG_ASSERT( size > in, "in overflow" ); | |
| 617 CYG_ASSERT( 0 <= in, "in overflow" ); | |
| 618 CYG_ASSERT( size >= count, "count overflow" ); | |
| 619 | |
| 620 itemqueue[ in ] = item; | |
| 621 | |
| 622 CYG_ASSERTCLASS( this, "Bad this pointer"); | |
| 623 | |
| 624 wakeup_waiter( get_threadq ); | |
| 625 | |
| 626 // Unlock the scheduler and maybe switch threads | |
| 627 Cyg_Scheduler::unlock(); | |
| 628 | |
| 629 return true; | |
| 630 } | |
| 631 | |
| 632 | |
| 633 // ------------------------------------------------------------------------- | |
| 634 #endif // ifndef CYGONCE_KERNEL_MBOXT_INL | |
| 635 // EOF mboxt.inl |
