µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os-mutex.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <cmsis-plus/rtos/os.h>
29
30// ----------------------------------------------------------------------------
31
32#if defined(__clang__)
33#pragma clang diagnostic ignored "-Wc++98-compat"
34#endif
35
36// ----------------------------------------------------------------------------
37
38namespace os
39{
40 namespace rtos
41 {
42 // ------------------------------------------------------------------------
43
294 const mutex::attributes mutex::initializer_normal;
295
300 const mutex::attributes_recursive mutex::initializer_recursive;
301
302 // ------------------------------------------------------------------------
303
305 mutex, utils::double_list_links, &mutex::owner_links_>;
306
307 // ------------------------------------------------------------------------
308
441 mutex::mutex (const attributes& attr) :
442 mutex
443 { nullptr, attr }
444 {
445 ;
446 }
447
478 mutex::mutex (const char* name, const attributes& attr) :
479 object_named_system
480 { name }, //
481 type_ (attr.mx_type), //
482 protocol_ (attr.mx_protocol), //
483 robustness_ (attr.mx_robustness), //
484 max_count_ ((attr.mx_type == type::recursive) ? attr.mx_max_count : 1)
485 {
486#if defined(OS_TRACE_RTOS_MUTEX)
487 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
488#endif
489
490 // Don't call this from interrupt handlers.
492
493 os_assert_throw(type_ <= type::max_, EINVAL);
494 os_assert_throw(protocol_ <= protocol::max_, EINVAL);
495 os_assert_throw(robustness_ <= robustness::max_, EINVAL);
496
497#if !defined(OS_USE_RTOS_PORT_MUTEX)
498 clock_ = attr.clock != nullptr ? attr.clock : &sysclock;
499#endif
500
501 os_assert_throw(attr.mx_priority_ceiling >= thread::priority::lowest,
502 EINVAL);
503 os_assert_throw(attr.mx_priority_ceiling <= thread::priority::highest,
504 EINVAL);
505
506 initial_prio_ceiling_ = attr.mx_priority_ceiling;
507 prio_ceiling_ = attr.mx_priority_ceiling;
508
509#if defined(OS_USE_RTOS_PORT_MUTEX)
510
511 count_ = 0;
512 port::mutex::create (this);
513
514#else
515
516 internal_init_ ();
517
518#endif
519 }
520
539 {
540#if defined(OS_TRACE_RTOS_MUTEX)
541 trace::printf ("%s() @%p %s\n", __func__, this, name ());
542#endif
543
544#if defined(OS_USE_RTOS_PORT_MUTEX)
545
546 port::mutex::destroy (this);
547
548#else
549
550 // The mutex must have no owner (must have been unlocked).
551 assert(owner_ == nullptr);
552 // There must be no threads waiting for this mutex.
553 assert(list_.empty ());
554
555#endif
556 }
557
562 void
563 mutex::internal_init_ (void)
564 {
565 owner_ = nullptr;
566 owner_links_.unlink ();
567 count_ = 0;
568 prio_ceiling_ = initial_prio_ceiling_;
569 boosted_prio_ = thread::priority::none;
570 owner_dead_ = false;
571 consistent_ = true;
572 recoverable_ = true;
573
574#if !defined(OS_USE_RTOS_PORT_MUTEX)
575
576 // Wake-up all threads, if any.
577 // Need not be inside the critical section,
578 // the list is protected by inner `resume_one()`.
579 list_.resume_all ();
580
581#endif
582 }
583
584 /*
585 * Internal function.
586 * Should be called from a scheduler critical section.
587 */
589 mutex::internal_try_lock_ (class thread* th)
590 {
591 // Save the initial owner for later protocol tests.
592 thread* saved_owner = owner_;
593
594 // First lock.
595 if (owner_ == nullptr)
596 {
597 // If the mutex has no owner, own it.
598 owner_ = th;
599
600 // For recursive mutexes, initialise counter.
601 count_ = 1;
602
603 // Add mutex to the thread list.
604 mutexes_list* th_list =
605 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
606 th_list->link (*this);
607
608#pragma GCC diagnostic push
609#if defined(__clang__)
610#pragma clang diagnostic ignored "-Wdeprecated-volatile"
611#endif
612 // Count the number of mutexes acquired by the thread.
613 ++(owner_->acquired_mutexes_);
614#pragma GCC diagnostic pop
615
616 if (protocol_ == protocol::protect)
617 {
618 if (th->priority () > prio_ceiling_)
619 {
620 // No need to keep the lock.
621 owner_ = nullptr;
622
623 // Prio ceiling must be at least the priority of the
624 // highest priority thread.
625 return EINVAL;
626 }
627
628 // POSIX: When a thread owns one or more mutexes
629 // initialised with the mutex::protocol::protect protocol,
630 // it shall execute at the higher of its priority or the
631 // highest of the priority ceilings of all the mutexes
632 // owned by this thread and initialised with this
633 // attribute, regardless of whether other threads are
634 // blocked on any of these robust mutexes or not.
635
636 // Boost priority.
637 boosted_prio_ = prio_ceiling_;
638 if (boosted_prio_ > owner_->priority_inherited ())
639 {
640 // ----- Enter uncritical section ---------------------------
641 scheduler::uncritical_section sucs;
642
643 owner_->priority_inherited (boosted_prio_);
644 // ----- Exit uncritical section ----------------------------
645 }
646 }
647
648#if defined(OS_TRACE_RTOS_MUTEX)
649 trace::printf ("%s() @%p %s by %p %s LCK\n", __func__, this, name (),
650 th, th->name ());
651#endif
652 // If the owning thread of a robust mutex terminates while
653 // holding the mutex lock, the next thread that acquires the
654 // mutex may be notified about the termination by the return
655 // value EOWNERDEAD.
656 if (owner_dead_)
657 {
658 // TODO: decide if the lock must be preserved.
659 return EOWNERDEAD;
660 }
661 return result::ok;
662 }
663
664 // Relock? (lock by the same thread).
665 if (saved_owner == th)
666 {
667 // The mutex was requested again by the same thread.
668 if (type_ == type::recursive)
669 {
670 if (count_ >= max_count_)
671 {
672 // The recursive mutex reached its limit.
673#if defined(OS_TRACE_RTOS_MUTEX)
674 trace::printf ("%s() @%p %s EAGAIN\n", __func__, this,
675 name ());
676#endif
677 return EAGAIN;
678 }
679
680#pragma GCC diagnostic push
681#if defined(__clang__)
682#pragma clang diagnostic ignored "-Wdeprecated-volatile"
683#endif
684 // Increment the recursion depth counter.
685 ++count_;
686#pragma GCC diagnostic pop
687
688#if defined(OS_TRACE_RTOS_MUTEX)
689 trace::printf ("%s() @%p %s by %p %s >%u\n", __func__, this,
690 name (), th, th->name (), count_);
691#endif
692 return result::ok;
693 }
694 else if (type_ == type::errorcheck)
695 {
696 // Errorcheck mutexes do not block, but return an error.
697#if defined(OS_TRACE_RTOS_MUTEX)
698 trace::printf ("%s() @%p %s EDEADLK\n", __func__, this, name ());
699#endif
700 return EDEADLK;
701 }
702 else if (type_ == type::normal)
703 {
704#if defined(OS_TRACE_RTOS_MUTEX)
705 trace::printf ("%s() @%p %s deadlock\n", __func__, this, name ());
706#endif
707 return EWOULDBLOCK;
708 }
709
710 return EWOULDBLOCK;
711 }
712 else
713 {
714 // Try to lock when not owner (another thread requested the mutex).
715
716 // POSIX: When a thread makes a call to mutex::lock(), the mutex was
717 // initialised with the protocol attribute having the value
718 // mutex::protocol::inherit, when the calling thread is blocked
719 // because the mutex is owned by another thread, that owner thread
720 // shall inherit the priority level of the calling thread as long
721 // as it continues to own the mutex. The implementation shall
722 // update its execution priority to the maximum of its assigned
723 // priority and all its inherited priorities.
724 // Furthermore, if this owner thread itself becomes blocked on
725 // another mutex with the protocol attribute having the value
726 // mutex::protocol::inherit, the same priority inheritance effect
727 // shall be propagated to this other owner thread, in a recursive
728 // manner.
729 if (protocol_ == protocol::inherit)
730 {
731 thread::priority_t prio = th->priority ();
732 boosted_prio_ = prio;
733
734 if (owner_links_.unlinked ())
735 {
736 mutexes_list* th_list =
737 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
738 th_list->link (*this);
739 }
740
741 // Boost owner priority.
742 if ((boosted_prio_ > owner_->priority_inherited ()))
743 {
744 // ----- Enter uncritical section ---------------------------
745 scheduler::uncritical_section sucs;
746
747 owner_->priority_inherited (boosted_prio_);
748 // ----- Exit uncritical section ----------------------------
749 }
750
751#if defined(OS_TRACE_RTOS_MUTEX)
752 trace::printf ("%s() @%p %s boost %u by %p %s \n", __func__, this,
753 name (), boosted_prio_, th, th->name ());
754#endif
755
756 return EWOULDBLOCK;
757 }
758 }
759
760 // Block anyway.
761 return EWOULDBLOCK;
762 }
763
765 mutex::internal_unlock_ (thread* th)
766 {
767 if (!recoverable_)
768 {
769 return ENOTRECOVERABLE;
770 }
771
772 {
773 // ----- Enter critical section -------------------------------------
774 scheduler::critical_section scs;
775
776 // Is the rightful owner?
777 if (owner_ == th)
778 {
779 if ((type_ == type::recursive) && (count_ > 1))
780 {
781#pragma GCC diagnostic push
782#if defined(__clang__)
783#pragma clang diagnostic ignored "-Wdeprecated-volatile"
784#endif
785 // Decrement the recursion depth counter.
786 --count_;
787#pragma GCC diagnostic pop
788
789#if defined(OS_TRACE_RTOS_MUTEX)
790 trace::printf ("%s() @%p %s >%u\n", __func__, this, name (),
791 count_);
792#endif
793 return result::ok;
794 }
795
796#pragma GCC diagnostic push
797#if defined(__clang__)
798#pragma clang diagnostic ignored "-Wdeprecated-volatile"
799#endif
800 --(owner_->acquired_mutexes_);
801#pragma GCC diagnostic pop
802
803 // Remove this mutex from the thread list; ineffective if
804 // not linked.
805 owner_links_.unlink ();
806
807 if (boosted_prio_ != thread::priority::none)
808 {
809 mutexes_list* thread_mutexes =
810 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
811
812 if (thread_mutexes->empty ())
813 {
814 // If the owner thread has no more mutexes,
815 // clear the inherited priority,
816 // and the assigned priority will take precedence.
817 boosted_prio_ = thread::priority::none;
818 }
819 else
820 {
821 // If the owner thread acquired other mutexes too,
822 // compute the maximum boosted priority.
823 thread::priority_t max_prio = 0;
824 for (auto&& mx : *thread_mutexes)
825 {
826 if (mx.boosted_prio_ > max_prio)
827 {
828 max_prio = mx.boosted_prio_;
829 }
830 }
831 boosted_prio_ = max_prio;
832 }
833 // Delayed until end of critical section.
834 owner_->priority_inherited (boosted_prio_);
835 }
836
837 // Delayed until end of critical section.
838 list_.resume_one ();
839
840 // Finally release the mutex.
841 owner_ = nullptr;
842 count_ = 0;
843
844#if defined(OS_TRACE_RTOS_MUTEX)
845 trace::printf ("%s() @%p %s ULCK\n", __func__, this, name ());
846#endif
847
848 // POSIX: If a robust mutex whose owner died is unlocked without
849 // a call to consistent(), it shall be in a permanently
850 // unusable state and all attempts to lock the mutex
851 // shall fail with the error ENOTRECOVERABLE.
852
853 if (owner_dead_)
854 {
855 owner_dead_ = false;
856
857 if (!consistent_)
858 {
859 recoverable_ = false;
860 return ENOTRECOVERABLE;
861 }
862 }
863
864 return result::ok;
865 }
866
867 // Not owner, or not locked.
868 if (type_ == type::errorcheck || type_ == type::recursive
869 || robustness_ == robustness::robust)
870 {
871#if defined(OS_TRACE_RTOS_MUTEX)
872 trace::printf ("%s() EPERM @%p %s \n", __func__, this, name ());
873#endif
874 return EPERM;
875 }
876
877 // Normal no-robust mutexes owned by other threads have
878 // undefined behaviour.
879
880#if defined(OS_TRACE_RTOS_MUTEX)
881 trace::printf ("%s() ENOTRECOVERABLE @%p %s \n", __func__, this,
882 name ());
883#endif
884 return ENOTRECOVERABLE;
885 // ----- Exit critical section --------------------------------------
886 }
887 }
888
889 // Called from thread termination, in a critical section.
890 void
891 mutex::internal_mark_owner_dead_ (void)
892 {
893 // May return error if not the rightful owner.
894 trace::printf ("%s() @%p %s\n", __func__, this, name ());
895
896 if (robustness_ == mutex::robustness::robust)
897 {
898 // If the owning thread of a robust mutex terminates
899 // while holding the mutex lock, the next thread that
900 // acquires the mutex may be notified about the termination
901 // by the return value EOWNERDEAD.
902 owner_dead_ = true;
903 consistent_ = false;
904 }
905 }
906
954 {
955#if defined(OS_TRACE_RTOS_MUTEX)
956 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
958#endif
959
960 // Don't call this from interrupt handlers.
962 // Don't try to lock a non-recursive mutex again.
964
965 if (!recoverable_)
966 {
967 return ENOTRECOVERABLE;
968 }
969
970#if defined(OS_USE_RTOS_PORT_MUTEX)
971
972 return port::mutex::lock (this);
973
974#else
975
976 thread& crt_thread = this_thread::thread ();
977
978 result_t res;
979 {
980 // ----- Enter critical section -------------------------------------
982
983 res = internal_try_lock_ (&crt_thread);
984 if (res != EWOULDBLOCK)
985 {
986 return res;
987 }
988 // ----- Exit critical section --------------------------------------
989 }
990
991 // Prepare a list node pointing to the current thread.
992 // Do not worry for being on stack, it is temporarily linked to the
993 // list and guaranteed to be removed before this function returns.
995 { crt_thread };
996
997 for (;;)
998 {
999 {
1000 // ----- Enter critical section ---------------------------------
1002
1003 res = internal_try_lock_ (&crt_thread);
1004 if (res != EWOULDBLOCK)
1005 {
1006 return res;
1007 }
1008
1009 {
1010 // ----- Enter critical section -----------------------------
1012
1013 // Add this thread to the mutex waiting list.
1014 scheduler::internal_link_node (list_, node);
1015 // state::suspended set in above link().
1016 // ----- Exit critical section ------------------------------
1017 }
1018 // ----- Exit critical section ----------------------------------
1019 }
1020
1022
1023 // Remove the thread from the semaphore waiting list,
1024 // if not already removed by unlock().
1025 scheduler::internal_unlink_node (node);
1026
1027 if (crt_thread.interrupted ())
1028 {
1029#if defined(OS_TRACE_RTOS_MUTEX)
1030 trace::printf ("%s() EINTR @%p %s\n", __func__, this, name ());
1031#endif
1032 return EINTR;
1033 }
1034 }
1035
1036 /* NOTREACHED */
1037 return ENOTRECOVERABLE;
1038
1039#endif
1040 }
1041
1073 result_t
1075 {
1076#if defined(OS_TRACE_RTOS_MUTEX)
1077 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1079#endif
1080
1081 // Don't call this from interrupt handlers.
1083
1084 if (!recoverable_)
1085 {
1086 return ENOTRECOVERABLE;
1087 }
1088
1089#if defined(OS_USE_RTOS_PORT_MUTEX)
1090
1091 return port::mutex::try_lock (this);
1092
1093#else
1094
1095 thread& crt_thread = this_thread::thread ();
1096
1097 {
1098 // ----- Enter critical section -------------------------------------
1100
1101 return internal_try_lock_ (&crt_thread);
1102 // ----- Exit critical section --------------------------------------
1103 }
1104
1105#endif
1106 }
1107
1149 result_t
1151 {
1152#if defined(OS_TRACE_RTOS_MUTEX)
1153 trace::printf ("%s(%u) @%p %s by %p %s\n", __func__,
1154 static_cast<unsigned int> (timeout), this, name (),
1156#endif
1157
1158 // Don't call this from interrupt handlers.
1160 // Don't try to lock a non-recursive mutex again.
1161 os_assert_err(!scheduler::locked (), EPERM);
1162
1163 if (!recoverable_)
1164 {
1165 return ENOTRECOVERABLE;
1166 }
1167
1168#if defined(OS_USE_RTOS_PORT_MUTEX)
1169
1170 return port::mutex::timed_lock (this, timeout);
1171
1172#else
1173
1174 thread& crt_thread = this_thread::thread ();
1175
1176 result_t res;
1177
1178 // Extra test before entering the loop, with its inherent weight.
1179 // Trade size for speed.
1180 {
1181 // ----- Enter critical section -------------------------------------
1183
1184 res = internal_try_lock_ (&crt_thread);
1185 if (res != EWOULDBLOCK)
1186 {
1187 return res;
1188 }
1189 // ----- Exit critical section --------------------------------------
1190 }
1191
1192 // Prepare a list node pointing to the current thread.
1193 // Do not worry for being on stack, it is temporarily linked to the
1194 // list and guaranteed to be removed before this function returns.
1196 { crt_thread };
1197
1198 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
1199 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
1200
1201 // Prepare a timeout node pointing to the current thread.
1203 { timeout_timestamp, crt_thread };
1204
1205 for (;;)
1206 {
1207 {
1208 // ----- Enter critical section ---------------------------------
1210
1211 res = internal_try_lock_ (&crt_thread);
1212 if (res != EWOULDBLOCK)
1213 {
1214 return res;
1215 }
1216
1217 {
1218 // ----- Enter critical section -----------------------------
1220
1221 // Add this thread to the mutex waiting list,
1222 // and the clock timeout list.
1223 scheduler::internal_link_node (list_, node, clock_list,
1224 timeout_node);
1225 // state::suspended set in above link().
1226 // ----- Exit critical section ------------------------------
1227 }
1228 // ----- Exit critical section ----------------------------------
1229 }
1230
1232
1233 // Remove the thread from the semaphore waiting list,
1234 // if not already removed by unlock() and from the clock
1235 // timeout list, if not already removed by the timer.
1236 scheduler::internal_unlink_node (node, timeout_node);
1237
1238 res = result::ok;
1239
1240 if (crt_thread.interrupted ())
1241 {
1242#if defined(OS_TRACE_RTOS_MUTEX)
1243 trace::printf ("%s() EINTR @%p %s \n", __func__, this, name ());
1244#endif
1245 res = EINTR;
1246 }
1247 else if (clock_->steady_now () >= timeout_timestamp)
1248 {
1249#if defined(OS_TRACE_RTOS_MUTEX)
1250 trace::printf ("%s() ETIMEDOUT @%p %s \n", __func__, this,
1251 name ());
1252#endif
1253 res = ETIMEDOUT;
1254 }
1255 if (res != result::ok)
1256 {
1257 if (boosted_prio_ != thread::priority::none)
1258 {
1259 // If the priority was boosted, it must be restored
1260 // to the highest priority of the waiting threads, if any.
1261
1263
1264 for (auto&& th : list_)
1265 {
1266 thread::priority_t prio = th.priority ();
1267 if (prio > max_prio)
1268 {
1269 max_prio = prio;
1270 }
1271 }
1272
1273 if (max_prio != thread::priority::none)
1274 {
1275 boosted_prio_ = max_prio;
1276 owner_->priority (boosted_prio_);
1277 }
1278 }
1279 return res;
1280 }
1281 }
1282
1283 /* NOTREACHED */
1284 return ENOTRECOVERABLE;
1285
1286#endif
1287 }
1288
1309 result_t
1311 {
1312#if defined(OS_TRACE_RTOS_MUTEX)
1313 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1315#endif
1316
1317 // Don't call this from interrupt handlers.
1319
1320#if defined(OS_USE_RTOS_PORT_MUTEX)
1321
1322 return port::mutex::unlock (this);
1323
1324#else
1325
1326 thread* crt_thread = &this_thread::thread ();
1327
1328 return internal_unlock_ (crt_thread);
1329
1330#endif
1331 }
1332
1346 {
1347#if defined(OS_TRACE_RTOS_MUTEX)
1348 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1349#endif
1350
1351 // Don't call this from interrupt handlers.
1352 assert(!interrupts::in_handler_mode ());
1353
1354#if defined(OS_USE_RTOS_PORT_MUTEX)
1355
1356 return port::mutex::prio_ceiling (this);
1357
1358#else
1359
1360 return prio_ceiling_;
1361
1362#endif
1363 }
1364
1385 result_t
1387 thread::priority_t* old_prio_ceiling)
1388 {
1389#if defined(OS_TRACE_RTOS_MUTEX)
1390 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1391#endif
1392
1393 // Don't call this from interrupt handlers.
1395
1396#if defined(OS_USE_RTOS_PORT_MUTEX)
1397
1398 return port::mutex::prio_ceiling (this, prio_ceiling, old_prio_ceiling);
1399
1400#else
1401
1402 // TODO: lock() must not adhere to the priority protocol.
1403 result_t res = lock ();
1404 if (res != result::ok)
1405 {
1406 return res;
1407 }
1408
1409 if (old_prio_ceiling != nullptr)
1410 {
1411 *old_prio_ceiling = prio_ceiling_;
1412 }
1413
1414 prio_ceiling_ = prio_ceiling;
1415
1416 unlock ();
1417
1418 return result::ok;
1419
1420#endif
1421 }
1422
1451 result_t
1453 {
1454#if defined(OS_TRACE_RTOS_MUTEX)
1455 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1456#endif
1457
1458 // Don't call this from interrupt handlers.
1460 // Don't call this for non-robust mutexes.
1461 os_assert_err(robustness_ == robustness::robust, EINVAL);
1462 // Don't call it if already consistent.
1463 os_assert_err(!consistent_, EINVAL);
1464
1465#if defined(OS_USE_RTOS_PORT_MUTEX)
1466
1467 return port::mutex::consistent (this);
1468
1469#else
1470
1471 // Update status to consistent.
1472 consistent_ = true;
1473 return result::ok;
1474
1475#endif
1476 }
1477
1488 result_t
1490 {
1491#if defined(OS_TRACE_RTOS_MUTEX)
1492 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1493#endif
1494
1495 // Don't call this from interrupt handlers.
1497
1498 {
1499 // ----- Enter critical section -------------------------------------
1501
1502 internal_init_ ();
1503 return result::ok;
1504 // ----- Exit critical section --------------------------------------
1505 }
1506
1507 }
1508
1509 // ==========================================================================
1510
1526 // --------------------------------------------------------------------------
1527 } /* namespace rtos */
1528} /* namespace os */
1529
1530// ----------------------------------------------------------------------------
Ordered list of time stamp nodes.
Definition os-lists.h:671
const char * name(void) const
Get object name.
Definition os-decls.h:774
Double linked list node, with time stamp and thread.
Definition os-lists.h:227
Double linked list node, with thread reference.
Definition os-lists.h:72
Interrupts critical section RAII helper.
Definition os-sched.h:524
Mutex attributes.
Definition os-mutex.h:219
POSIX compliant mutex.
Definition os-mutex.h:65
result_t reset(void)
Reset the mutex.
result_t lock(void)
Lock/acquire the mutex.
Definition os-mutex.cpp:953
thread::priority_t prio_ceiling(void) const
Get the priority ceiling of a mutex.
mutex(const attributes &attr=initializer_normal)
Construct a mutex object instance.
Definition os-mutex.cpp:441
result_t timed_lock(clock::duration_t timeout)
Timed attempt to lock/acquire the mutex.
result_t try_lock(void)
Try to lock/acquire the mutex.
~mutex()
Destruct the mutex object instance.
Definition os-mutex.cpp:538
result_t consistent(void)
Mark mutex as consistent.
result_t unlock(void)
Unlock/release the mutex.
Scheduler critical section RAII helper.
Definition os-sched.h:182
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:247
bool interrupted(void)
Check if interrupted.
Definition os-thread.h:2361
List of intrusive nodes.
Definition lists.h:721
Standard thread.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:74
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:83
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:92
clock_systick sysclock
The system clock object instance.
static const attributes_recursive initializer_recursive
Default recursive mutex initialiser.
Definition os-mutex.h:362
static const attributes initializer_normal
Default normal mutex initialiser.
Definition os-mutex.h:313
uint8_t priority_t
Type of variables holding thread priorities.
Definition os-thread.h:268
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1136
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:195
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:882
thread & thread(void)
Get the current running thread.
utils::intrusive_list< mutex, utils::double_list_links, &mutex::owner_links_ > mutexes_list
Definition os-mutex.cpp:305
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:110
System namespace.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
Definition os-decls.h:1141
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1126
Single file µOS++ RTOS definitions.
@ inherit
Inherit priority from highest priority thread.
Definition os-mutex.h:95
@ protect
Execute at the highest priority.
Definition os-mutex.h:100
@ robust
Enhanced robustness at thread termination.
Definition os-mutex.h:141
@ normal
Normal mutex behaviour.
Definition os-mutex.h:177
@ errorcheck
Check mutex behaviour.
Definition os-mutex.h:181
@ recursive
Recursive mutex behaviour.
Definition os-mutex.h:185