comparison packages/kernel/current/src/sync/mutex.cxx @ 115:6ed91473a1cd ecos-sw-2000-08-21

Merge from eCos master repository on 2000-08-21-22:40:54-BST
author jlarmour
date Fri, 25 Aug 2000 17:32:38 +0000
parents 59d97b6ba612
children 0ec04793409a
comparison
equal deleted inserted replaced
114:5ad2b71d525e 115:6ed91473a1cd
53 53
54 #include <cyg/kernel/thread.inl> // thread inlines 54 #include <cyg/kernel/thread.inl> // thread inlines
55 #include <cyg/kernel/sched.inl> // scheduler inlines 55 #include <cyg/kernel/sched.inl> // scheduler inlines
56 #include <cyg/kernel/clock.inl> // clock inlines 56 #include <cyg/kernel/clock.inl> // clock inlines
57 57
58 // -------------------------------------------------------------------------
59 // Mutex protocol test macros.
60 // If the dynamic protocol option is enabled, then these generate appropriate
61 // tests on the protocol field. If there is no dynamic choice then they simply
62 // result in empty statements.
63
64 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
65
66 #define IF_PROTOCOL_INHERIT if( protocol == INHERIT )
67 #define IF_PROTOCOL_CEILING if( protocol == CEILING )
68
69 #else
70
71 #define IF_PROTOCOL_INHERIT
72 #define IF_PROTOCOL_CEILING
73
74 #endif
58 75
59 // ------------------------------------------------------------------------- 76 // -------------------------------------------------------------------------
60 // Constructor 77 // Constructor
61 78
62 Cyg_Mutex::Cyg_Mutex() 79 Cyg_Mutex::Cyg_Mutex()
64 CYG_REPORT_FUNCTION(); 81 CYG_REPORT_FUNCTION();
65 82
66 locked = false; 83 locked = false;
67 owner = NULL; 84 owner = NULL;
68 85
69 CYG_REPORT_RETURN(); 86 #if defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT) && \
70 } 87 defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC)
88
89 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
90 protocol = INHERIT;
91 #endif
92 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_CEILING
93 protocol = CEILING;
94 ceiling = CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY;
95 #endif
96 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_NONE
97 protocol = NONE;
98 #endif
99
100 #endif
101
102 CYG_REPORT_RETURN();
103 }
104
105 // -------------------------------------------------------------------------
106 // Construct with defined protocol
107
108 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
109
110 Cyg_Mutex::Cyg_Mutex( cyg_protcol protocol_arg )
111 {
112 CYG_REPORT_FUNCTION();
113
114 locked = false;
115 owner = NULL;
116
117 protocol = protocol_arg;
118
119 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
120 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY
121
122 // if there is a default priority ceiling defined, use that to initialize
123 // the ceiling.
124 ceiling = CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY;
125
126 #else
127
128 // Otherwise set it to zero.
129 ceiling = 0;
130
131 #endif
132 #endif
133
134 CYG_REPORT_RETURN();
135 }
136
137 #endif
71 138
72 // ------------------------------------------------------------------------- 139 // -------------------------------------------------------------------------
73 // Destructor 140 // Destructor
74 141
75 Cyg_Mutex::~Cyg_Mutex() 142 Cyg_Mutex::~Cyg_Mutex()
133 // Loop while the mutex is locked, sleeping each time around 200 // Loop while the mutex is locked, sleeping each time around
134 // the loop. This copes with the possibility of a higher priority 201 // the loop. This copes with the possibility of a higher priority
135 // thread grabbing the mutex between the wakeup in unlock() and 202 // thread grabbing the mutex between the wakeup in unlock() and
136 // this thread actually starting. 203 // this thread actually starting.
137 204
138 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 205 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
139 206
140 self->count_mutex(); 207 self->count_mutex();
141 208
142 #endif 209 #endif
143 210
149 216
150 self->sleep(); 217 self->sleep();
151 218
152 queue.enqueue( self ); 219 queue.enqueue( self );
153 220
154 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 221 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
155 222
156 owner->inherit_priority(self); 223 IF_PROTOCOL_INHERIT
224 owner->inherit_priority(self);
157 225
158 #endif 226 #endif
159 227
160 CYG_INSTRUMENT_MUTEX(WAIT, this, 0); 228 CYG_INSTRUMENT_MUTEX(WAIT, this, 0);
161 229
162 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock"); 230 // Allow other threads to run
163 231 Cyg_Scheduler::reschedule();
164 // Unlock scheduler and allow other threads 232
165 // to run
166 Cyg_Scheduler::unlock();
167 Cyg_Scheduler::lock();
168
169 CYG_ASSERTCLASS( this, "Bad this pointer"); 233 CYG_ASSERTCLASS( this, "Bad this pointer");
170 234
171 switch( self->get_wake_reason() ) 235 switch( self->get_wake_reason() )
172 { 236 {
173 case Cyg_Thread::DESTRUCT: 237 case Cyg_Thread::DESTRUCT:
188 if( result ) 252 if( result )
189 { 253 {
190 locked = true; 254 locked = true;
191 owner = self; 255 owner = self;
192 256
257 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
258
259 IF_PROTOCOL_CEILING
260 self->set_priority_ceiling(ceiling);
261
262 #endif
263
193 CYG_INSTRUMENT_MUTEX(LOCKED, this, 0); 264 CYG_INSTRUMENT_MUTEX(LOCKED, this, 0);
194 } 265 }
195 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 266 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
196 else 267 else
197 { 268 {
198 self->uncount_mutex(); 269 IF_PROTOCOL_INHERIT
199 self->disinherit_priority(); 270 {
271 self->uncount_mutex();
272 self->disinherit_priority();
273 }
200 } 274 }
201 #endif 275 #endif
202 276
203 // Unlock the scheduler and maybe switch threads 277 // Unlock the scheduler and maybe switch threads
204 Cyg_Scheduler::unlock(); 278 Cyg_Scheduler::unlock();
232 Cyg_Thread *self = Cyg_Thread::self(); 306 Cyg_Thread *self = Cyg_Thread::self();
233 307
234 locked = true; 308 locked = true;
235 owner = self; 309 owner = self;
236 310
237 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 311 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
238 312
239 self->count_mutex(); 313 self->count_mutex();
240 314
241 #endif 315 #endif
316 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
317
318 IF_PROTOCOL_CEILING
319 self->set_priority_ceiling(ceiling);
320
321 #endif
322
242 } 323 }
243 else result = false; 324 else result = false;
244 325
245 CYG_INSTRUMENT_MUTEX(TRY, this, result); 326 CYG_INSTRUMENT_MUTEX(TRY, this, result);
246 327
275 356
276 Cyg_Thread *thread = queue.dequeue(); 357 Cyg_Thread *thread = queue.dequeue();
277 358
278 CYG_ASSERTCLASS( thread, "Bad thread pointer"); 359 CYG_ASSERTCLASS( thread, "Bad thread pointer");
279 360
280 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 361 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
281 362
282 // Give the owner-to-be a chance to inherit from the remaining 363 // Give the owner-to-be a chance to inherit from the remaining
283 // queue or the relinquishing thread: 364 // queue or the relinquishing thread:
284 365
285 thread->relay_priority(owner, &queue); 366 IF_PROTOCOL_INHERIT
367 thread->relay_priority(owner, &queue);
286 368
287 #endif 369 #endif
288 370
289 thread->set_wake_reason( Cyg_Thread::DONE ); 371 thread->set_wake_reason( Cyg_Thread::DONE );
290 372
292 374
293 CYG_INSTRUMENT_MUTEX(WAKE, this, thread); 375 CYG_INSTRUMENT_MUTEX(WAKE, this, thread);
294 376
295 } 377 }
296 378
297 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE 379 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL
298 380
299 owner->uncount_mutex(); 381 owner->uncount_mutex();
300 owner->disinherit_priority(); 382
301 383 #endif
384 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
385
386 IF_PROTOCOL_INHERIT
387 owner->disinherit_priority();
388
389 #endif
390 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
391
392 IF_PROTOCOL_CEILING
393 owner->clear_priority_ceiling();
394
302 #endif 395 #endif
303 396
304 locked = false; 397 locked = false;
305 owner = NULL; 398 owner = NULL;
306 399
346 // Unlock the scheduler and maybe switch threads 439 // Unlock the scheduler and maybe switch threads
347 Cyg_Scheduler::unlock(); 440 Cyg_Scheduler::unlock();
348 441
349 CYG_REPORT_RETURN(); 442 CYG_REPORT_RETURN();
350 } 443 }
444
445 // -------------------------------------------------------------------------
446 // Set ceiling priority for priority ceiling protocol
447
448 #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
449
450 void Cyg_Mutex::set_ceiling( cyg_priority priority )
451 {
452 CYG_REPORT_FUNCTION();
453
454 // CYG_ASSERT( priority >= CYG_THREAD_MAX_PRIORITY, "Priority out of range");
455 // CYG_ASSERT( priority <= CYG_THREAD_MIN_PRIORITY, "Priority out of range");
456
457 // Prevent preemption
458 Cyg_Scheduler::lock();
459
460 ceiling = priority;
461
462 // Unlock the scheduler
463 Cyg_Scheduler::unlock();
464
465 CYG_REPORT_RETURN();
466 }
467
468 #endif
351 469
352 //========================================================================== 470 //==========================================================================
353 // Condition variables 471 // Condition variables
354 472
355 Cyg_Condition_Variable::Cyg_Condition_Variable( 473 Cyg_Condition_Variable::Cyg_Condition_Variable(
359 CYG_REPORT_FUNCTION(); 477 CYG_REPORT_FUNCTION();
360 478
361 mutex = &mx; 479 mutex = &mx;
362 480
363 CYG_ASSERTCLASS( mutex, "Invalid mutex argument"); 481 CYG_ASSERTCLASS( mutex, "Invalid mutex argument");
482
483 CYG_REPORT_RETURN();
484 }
485
486 Cyg_Condition_Variable::Cyg_Condition_Variable()
487 {
488 CYG_REPORT_FUNCTION();
489
490 mutex = NULL;
364 491
365 CYG_REPORT_RETURN(); 492 CYG_REPORT_RETURN();
366 } 493 }
367 494
368 // ------------------------------------------------------------------------- 495 // -------------------------------------------------------------------------
397 switch( zeal ) 524 switch( zeal )
398 { 525 {
399 case cyg_system_test: 526 case cyg_system_test:
400 case cyg_extreme: 527 case cyg_extreme:
401 case cyg_thorough: 528 case cyg_thorough:
402 if( !mutex->check_this(zeal) ) 529 if( mutex != NULL && !mutex->check_this(zeal) )
403 result = false; 530 result = false;
404 case cyg_quick: 531 case cyg_quick:
405 case cyg_trivial: 532 case cyg_trivial:
406 case cyg_none: 533 case cyg_none:
407 default: 534 default:
420 // Note: if this function is entered with the scheduler locked (e.g. to 547 // Note: if this function is entered with the scheduler locked (e.g. to
421 // suspend DSR processing) then there is no need to take the lock. Also 548 // suspend DSR processing) then there is no need to take the lock. Also
422 // in this case, exit with the scheduler locked, which allows this function 549 // in this case, exit with the scheduler locked, which allows this function
423 // to be used in a totally thread-safe manner. 550 // to be used in a totally thread-safe manner.
424 551
425 void 552 cyg_bool
426 Cyg_Condition_Variable::wait(void) 553 Cyg_Condition_Variable::wait_inner( Cyg_Mutex *mx )
427 { 554 {
428 CYG_REPORT_FUNCTION(); 555 CYG_REPORT_FUNCTION();
429 556
557 cyg_bool result = true;
430 Cyg_Thread *self = Cyg_Thread::self(); 558 Cyg_Thread *self = Cyg_Thread::self();
431 559
432 cyg_int32 current_lock = Cyg_Scheduler::get_sched_lock(); 560 cyg_int32 current_lock = Cyg_Scheduler::get_sched_lock();
433 561
434 if (current_lock == 0) 562 if (current_lock == 0)
435 // Prevent preemption 563 // Prevent preemption
436 Cyg_Scheduler::lock(); 564 Cyg_Scheduler::lock();
437 565
438 CYG_ASSERTCLASS( this, "Bad this pointer"); 566 CYG_ASSERTCLASS( this, "Bad this pointer");
439 CYG_ASSERTCLASS( mutex, "Corrupt mutex"); 567 CYG_ASSERTCLASS( mx, "Corrupt mutex");
440 CYG_ASSERTCLASS( self, "Bad self thread"); 568 CYG_ASSERTCLASS( self, "Bad self thread");
441 569
442 CYG_INSTRUMENT_CONDVAR(WAIT, this, 0); 570 CYG_INSTRUMENT_CONDVAR(WAIT, this, 0);
443 571
444 mutex->unlock(); 572 mx->unlock();
445 573
446 self->set_sleep_reason( Cyg_Thread::WAIT ); 574 self->set_sleep_reason( Cyg_Thread::WAIT );
447 575
448 self->sleep(); 576 self->sleep();
449 577
450 queue.enqueue( self ); 578 queue.enqueue( self );
451 579
452 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock"); 580 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock");
581
582 // Avoid calling ASRs during the following unlock.
583 self->set_asr_inhibit();
453 584
454 // Unlock the scheduler and switch threads 585 // Unlock the scheduler and switch threads
455 Cyg_Scheduler::unlock(); 586 Cyg_Scheduler::unlock();
456 587
588 // Allow ASRs again
589 self->clear_asr_inhibit();
590
457 CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason()); 591 CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason());
458 592
459 CYG_ASSERTCLASS( this, "Bad this pointer"); 593 CYG_ASSERTCLASS( this, "Bad this pointer");
460 CYG_ASSERTCLASS( mutex, "Corrupt mutex"); 594 CYG_ASSERTCLASS( mx, "Corrupt mutex");
461 595
462 switch( self->get_wake_reason() ) 596 switch( self->get_wake_reason() )
463 { 597 {
598 case Cyg_Thread::DESTRUCT: // which, the cv or the mutex?
599 case Cyg_Thread::BREAK:
600 result = false;
601 break;
602
464 case Cyg_Thread::EXIT: 603 case Cyg_Thread::EXIT:
465 self->exit(); 604 self->exit();
466 break; 605 break;
467 606
468 default: 607 default:
469 break; 608 break;
470 } 609 }
471
472 610
473 // When we awake, we must re-acquire the mutex. Note that while 611 // When we awake, we must re-acquire the mutex. Note that while
474 // it is essential to release the mutex and queue on the CV 612 // it is essential to release the mutex and queue on the CV
475 // atomically relative to other threads, to avoid races, it is not 613 // atomically relative to other threads, to avoid races, it is not
476 // necessary for us to re-acquire the mutex in the same atomic 614 // necessary for us to re-acquire the mutex in the same atomic
477 // action. Hence we can do it after unlocking the scheduler. 615 // action. Hence we can do it after unlocking the scheduler.
478 // We need to loop here in case the thread is released while waiting 616 // We need to loop here in case the thread is released while waiting
479 // for the mutex. It is essential that we exit this function with the 617 // for the mutex. It is essential that we exit this function with the
480 // mutex claimed. 618 // mutex claimed.
481 619
482 while ( !mutex->lock() ) 620 while ( !mx->lock() )
483 continue; 621 continue;
484 622
485 CYG_ASSERTCLASS( this, "Bad this pointer"); 623 CYG_ASSERTCLASS( this, "Bad this pointer");
486 CYG_ASSERTCLASS( mutex, "Corrupt mutex"); 624 CYG_ASSERTCLASS( mx, "Corrupt mutex");
487 CYG_ASSERT( mutex->owner == self, "Not mutex owner"); 625 CYG_ASSERT( mx->owner == self, "Not mutex owner");
488 626
489 CYG_REPORT_RETURN(); 627 CYG_REPORT_RETURN();
490 628
491 if (current_lock) 629 if (current_lock)
492 // Reacquire the DSR pseudo lock 630 // Reacquire the DSR pseudo lock
493 Cyg_Scheduler::lock(); 631 Cyg_Scheduler::lock();
632
633 return result;
494 } 634 }
495 635
496 // ------------------------------------------------------------------------- 636 // -------------------------------------------------------------------------
497 // Wake one thread 637 // Wake one thread
498 638
500 Cyg_Condition_Variable::signal(void) 640 Cyg_Condition_Variable::signal(void)
501 { 641 {
502 CYG_REPORT_FUNCTION(); 642 CYG_REPORT_FUNCTION();
503 643
504 CYG_ASSERTCLASS( this, "Bad this pointer"); 644 CYG_ASSERTCLASS( this, "Bad this pointer");
505 CYG_ASSERTCLASS( mutex, "Corrupt mutex");
506 645
507 // Prevent preemption 646 // Prevent preemption
508 Cyg_Scheduler::lock(); 647 Cyg_Scheduler::lock();
509 648
510 CYG_INSTRUMENT_CONDVAR(SIGNAL, this, 0); 649 CYG_INSTRUMENT_CONDVAR(SIGNAL, this, 0);
525 CYG_INSTRUMENT_CONDVAR(WAKE, this, thread); 664 CYG_INSTRUMENT_CONDVAR(WAKE, this, thread);
526 665
527 } 666 }
528 667
529 CYG_ASSERTCLASS( this, "Bad this pointer"); 668 CYG_ASSERTCLASS( this, "Bad this pointer");
530 CYG_ASSERTCLASS( mutex, "Corrupt mutex");
531 669
532 // Unlock the scheduler and maybe switch threads 670 // Unlock the scheduler and maybe switch threads
533 Cyg_Scheduler::unlock(); 671 Cyg_Scheduler::unlock();
534 672
535 CYG_REPORT_RETURN(); 673 CYG_REPORT_RETURN();
542 Cyg_Condition_Variable::broadcast(void) 680 Cyg_Condition_Variable::broadcast(void)
543 { 681 {
544 CYG_REPORT_FUNCTION(); 682 CYG_REPORT_FUNCTION();
545 683
546 CYG_ASSERTCLASS( this, "Bad this pointer"); 684 CYG_ASSERTCLASS( this, "Bad this pointer");
547 CYG_ASSERTCLASS( mutex, "Corrupt mutex");
548 685
549 // Prevent preemption 686 // Prevent preemption
550 Cyg_Scheduler::lock(); 687 Cyg_Scheduler::lock();
551 688
552 CYG_INSTRUMENT_CONDVAR(BROADCAST, this, 0); 689 CYG_INSTRUMENT_CONDVAR(BROADCAST, this, 0);
566 703
567 CYG_INSTRUMENT_CONDVAR(WAKE, this, thread); 704 CYG_INSTRUMENT_CONDVAR(WAKE, this, thread);
568 } 705 }
569 706
570 CYG_ASSERTCLASS( this, "Bad this pointer"); 707 CYG_ASSERTCLASS( this, "Bad this pointer");
571 CYG_ASSERTCLASS( mutex, "Corrupt mutex");
572 708
573 // Unlock the scheduler and maybe switch threads 709 // Unlock the scheduler and maybe switch threads
574 Cyg_Scheduler::unlock(); 710 Cyg_Scheduler::unlock();
575 711
576 CYG_REPORT_RETURN(); 712 CYG_REPORT_RETURN();
580 // Optional timed wait on a CV 716 // Optional timed wait on a CV
581 717
582 #if defined(CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT) 718 #if defined(CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT)
583 719
584 cyg_bool 720 cyg_bool
585 Cyg_Condition_Variable::wait( cyg_tick_count timeout ) 721 Cyg_Condition_Variable::wait_inner( Cyg_Mutex *mx, cyg_tick_count timeout )
586 { 722 {
587 CYG_REPORT_FUNCTYPE("returning %d"); 723 CYG_REPORT_FUNCTYPE("returning %d");
588 CYG_REPORT_FUNCARG1("timeout = %d", timeout); 724 CYG_REPORT_FUNCARG1("timeout = %d", timeout);
589 725
590 CYG_ASSERTCLASS( this, "Bad this pointer"); 726 CYG_ASSERTCLASS( this, "Bad this pointer");
591 CYG_ASSERTCLASS( mutex, "Corrupt mutex"); 727 CYG_ASSERTCLASS( mx, "Corrupt mutex");
592 728
593 cyg_bool result = true; 729 cyg_bool result = true;
594 730
595 Cyg_Thread *self = Cyg_Thread::self(); 731 Cyg_Thread *self = Cyg_Thread::self();
596 732
599 // Prevent preemption 735 // Prevent preemption
600 Cyg_Scheduler::lock(); 736 Cyg_Scheduler::lock();
601 737
602 CYG_INSTRUMENT_CONDVAR(TIMED_WAIT, this, 0 ); 738 CYG_INSTRUMENT_CONDVAR(TIMED_WAIT, this, 0 );
603 739
604 mutex->unlock(); 740 mx->unlock();
605 741
606 // The ordering of sleep() and set_timer() here are 742 // The ordering of sleep() and set_timer() here are
607 // important. If the timeout is in the past, the thread 743 // important. If the timeout is in the past, the thread
608 // will be woken up immediately and will not sleep. 744 // will be woken up immediately and will not sleep.
609 745
615 // Only enqueue if the timeout has not already fired. 751 // Only enqueue if the timeout has not already fired.
616 if( self->get_wake_reason() == Cyg_Thread::NONE ) 752 if( self->get_wake_reason() == Cyg_Thread::NONE )
617 queue.enqueue( self ); 753 queue.enqueue( self );
618 754
619 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock"); 755 CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock");
620 756
757 // Avoid calling ASRs during the following unlock.
758 self->set_asr_inhibit();
759
621 // Unlock the scheduler and switch threads 760 // Unlock the scheduler and switch threads
622 Cyg_Scheduler::unlock(); 761 Cyg_Scheduler::unlock();
623 762
624 CYG_ASSERTCLASS( this, "Bad this pointer"); 763 // Allow ASRs again
625 CYG_ASSERTCLASS( mutex, "Corrupt mutex"); 764 self->clear_asr_inhibit();
765
766 CYG_ASSERTCLASS( this, "Bad this pointer");
767 CYG_ASSERTCLASS( mx, "Corrupt mutex");
626 768
627 self->clear_timer(); 769 self->clear_timer();
628 770
629 CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason()); 771 CYG_INSTRUMENT_CONDVAR(WOKE, this, self->get_wake_reason());
630 772
649 // it is essential to release the mutex and queue on the CV 791 // it is essential to release the mutex and queue on the CV
650 // atomically relative to other threads, to avoid races, it is not 792 // atomically relative to other threads, to avoid races, it is not
651 // necessary for us to re-acquire the mutex in the same atomic 793 // necessary for us to re-acquire the mutex in the same atomic
652 // action. Hence we can do it after unlocking the scheduler. 794 // action. Hence we can do it after unlocking the scheduler.
653 795
654 // FIXME: what if we woke up above due to TIMEOUT/DESTRUCT/BREAK? 796 while ( !mx->lock() )
655 // In that situation is it correct to not lock the mutex? 797 continue;
656 if (false != result) 798
657 result = mutex->lock(); 799 CYG_ASSERTCLASS( this, "Bad this pointer");
658 800 CYG_ASSERTCLASS( mx, "Corrupt mutex");
659 CYG_ASSERTCLASS( this, "Bad this pointer");
660 CYG_ASSERTCLASS( mutex, "Corrupt mutex");
661 801
662 CYG_REPORT_RETVAL(result); 802 CYG_REPORT_RETVAL(result);
663 803
664 return result; 804 return result;
665 } 805 }