µ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++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2016-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
14#endif
15
16#include <cmsis-plus/rtos/os.h>
17
18// ----------------------------------------------------------------------------
19
20#if defined(__clang__)
21#pragma clang diagnostic ignored "-Wc++98-compat"
22#endif
23
24// ----------------------------------------------------------------------------
25
26namespace os
27{
28 namespace rtos
29 {
30 // ------------------------------------------------------------------------
31
317 const mutex::attributes mutex::initializer_normal;
318
323 const mutex::attributes_recursive mutex::initializer_recursive;
324
325 // ------------------------------------------------------------------------
326
328 &mutex::owner_links_>;
329
330 // ------------------------------------------------------------------------
331
470 mutex::mutex (const attributes& attr) : mutex{ nullptr, attr }
471 {
472 }
473
507 mutex::mutex (const char* name, const attributes& attr)
508 : object_named_system{ name }, //
509 type_ (attr.mx_type), //
510 protocol_ (attr.mx_protocol), //
511 robustness_ (attr.mx_robustness), //
512 max_count_ ((attr.mx_type == type::recursive) ? attr.mx_max_count
513 : 1)
514 {
515#if defined(OS_TRACE_RTOS_MUTEX)
516 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
517#endif
518
519 // Don't call this from interrupt handlers.
521
522 os_assert_throw (type_ <= type::max_, EINVAL);
523 os_assert_throw (protocol_ <= protocol::max_, EINVAL);
524 os_assert_throw (robustness_ <= robustness::max_, EINVAL);
525
526#if !defined(OS_USE_RTOS_PORT_MUTEX)
527 clock_ = attr.clock != nullptr ? attr.clock : &sysclock;
528#endif
529
531 EINVAL);
533 EINVAL);
534
535 initial_prio_ceiling_ = attr.mx_priority_ceiling;
536 prio_ceiling_ = attr.mx_priority_ceiling;
537
538#if defined(OS_USE_RTOS_PORT_MUTEX)
539
540 count_ = 0;
541 port::mutex::create (this);
542
543#else
544
545 internal_init_ ();
546
547#endif
548 }
549
571 {
572#if defined(OS_TRACE_RTOS_MUTEX)
573 trace::printf ("%s() @%p %s\n", __func__, this, name ());
574#endif
575
576#if defined(OS_USE_RTOS_PORT_MUTEX)
577
578 port::mutex::destroy (this);
579
580#else
581
582 // The mutex must have no owner (must have been unlocked).
583 assert (owner_ == nullptr);
584 // There must be no threads waiting for this mutex.
585 assert (list_.empty ());
586
587#endif
588 }
589
594 void
595 mutex::internal_init_ (void)
596 {
597 owner_ = nullptr;
598 owner_links_.unlink ();
599 count_ = 0;
600 prio_ceiling_ = initial_prio_ceiling_;
601 boosted_prio_ = thread::priority::none;
602 owner_dead_ = false;
603 consistent_ = true;
604 recoverable_ = true;
605
606#if !defined(OS_USE_RTOS_PORT_MUTEX)
607
608 // Wake-up all threads, if any.
609 // Need not be inside the critical section,
610 // the list is protected by inner `resume_one()`.
611 list_.resume_all ();
612
613#endif
614 }
615
616 /*
617 * Internal function.
618 * Should be called from a scheduler critical section.
619 */
621 mutex::internal_try_lock_ (/* class */ thread* th)
622 {
623 // Save the initial owner for later protocol tests.
624 thread* saved_owner = owner_;
625
626 // First lock.
627 if (owner_ == nullptr)
628 {
629 // If the mutex has no owner, own it.
630 owner_ = th;
631
632 // For recursive mutexes, initialise counter.
633 count_ = 1;
634
635 // Add mutex to the thread list.
636 mutexes_list* th_list
637 = reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
638 th_list->link (*this);
639
640#pragma GCC diagnostic push
641#if defined(__clang__)
642#pragma clang diagnostic ignored "-Wdeprecated-volatile"
643#elif defined(__GNUC__)
644#pragma GCC diagnostic ignored "-Wvolatile"
645#endif
646 // Count the number of mutexes acquired by the thread.
647 ++(owner_->acquired_mutexes_);
648#pragma GCC diagnostic pop
649
650 if (protocol_ == protocol::protect)
651 {
652 if (th->priority () > prio_ceiling_)
653 {
654 // No need to keep the lock.
655 owner_ = nullptr;
656
657 // Prio ceiling must be at least the priority of the
658 // highest priority thread.
659 return EINVAL;
660 }
661
662 // POSIX: When a thread owns one or more mutexes
663 // initialised with the mutex::protocol::protect protocol,
664 // it shall execute at the higher of its priority or the
665 // highest of the priority ceilings of all the mutexes
666 // owned by this thread and initialised with this
667 // attribute, regardless of whether other threads are
668 // blocked on any of these robust mutexes or not.
669
670 // Boost priority.
671 boosted_prio_ = prio_ceiling_;
672 if (boosted_prio_ > owner_->priority_inherited ())
673 {
674 // ----- Enter uncritical section ---------------------------
675 scheduler::uncritical_section sucs;
676
677 owner_->priority_inherited (boosted_prio_);
678 // ----- Exit uncritical section ----------------------------
679 }
680 }
681
682#if defined(OS_TRACE_RTOS_MUTEX)
683 trace::printf ("%s() @%p %s by %p %s LCK\n", __func__, this, name (),
684 th, th->name ());
685#endif
686 // If the owning thread of a robust mutex terminates while
687 // holding the mutex lock, the next thread that acquires the
688 // mutex may be notified about the termination by the return
689 // value EOWNERDEAD.
690 if (owner_dead_)
691 {
692 // TODO: decide if the lock must be preserved.
693 return EOWNERDEAD;
694 }
695 return result::ok;
696 }
697
698 // Relock? (lock by the same thread).
699 if (saved_owner == th)
700 {
701 // The mutex was requested again by the same thread.
702 if (type_ == type::recursive)
703 {
704 if (count_ >= max_count_)
705 {
706 // The recursive mutex reached its limit.
707#if defined(OS_TRACE_RTOS_MUTEX)
708 trace::printf ("%s() @%p %s EAGAIN\n", __func__, this,
709 name ());
710#endif
711 return EAGAIN;
712 }
713
714#pragma GCC diagnostic push
715#if defined(__clang__)
716#pragma clang diagnostic ignored "-Wdeprecated-volatile"
717#elif defined(__GNUC__)
718#pragma GCC diagnostic ignored "-Wvolatile"
719#endif
720 // Increment the recursion depth counter.
721 ++count_;
722#pragma GCC diagnostic pop
723
724#if defined(OS_TRACE_RTOS_MUTEX)
725 trace::printf ("%s() @%p %s by %p %s >%u\n", __func__, this,
726 name (), th, th->name (), count_);
727#endif
728 return result::ok;
729 }
730 else if (type_ == type::errorcheck)
731 {
732 // Errorcheck mutexes do not block, but return an error.
733#if defined(OS_TRACE_RTOS_MUTEX)
734 trace::printf ("%s() @%p %s EDEADLK\n", __func__, this, name ());
735#endif
736 return EDEADLK;
737 }
738 else if (type_ == type::normal)
739 {
740#if defined(OS_TRACE_RTOS_MUTEX)
741 trace::printf ("%s() @%p %s deadlock\n", __func__, this,
742 name ());
743#endif
744 return EWOULDBLOCK;
745 }
746
747 return EWOULDBLOCK;
748 }
749 else
750 {
751 // Try to lock when not owner (another thread requested the mutex).
752
753 // POSIX: When a thread makes a call to mutex::lock(), the mutex was
754 // initialised with the protocol attribute having the value
755 // mutex::protocol::inherit, when the calling thread is blocked
756 // because the mutex is owned by another thread, that owner thread
757 // shall inherit the priority level of the calling thread as long
758 // as it continues to own the mutex. The implementation shall
759 // update its execution priority to the maximum of its assigned
760 // priority and all its inherited priorities.
761 // Furthermore, if this owner thread itself becomes blocked on
762 // another mutex with the protocol attribute having the value
763 // mutex::protocol::inherit, the same priority inheritance effect
764 // shall be propagated to this other owner thread, in a recursive
765 // manner.
766 if (protocol_ == protocol::inherit)
767 {
768 thread::priority_t prio = th->priority ();
769 boosted_prio_ = prio;
770
771 if (owner_links_.unlinked ())
772 {
773 mutexes_list* th_list
774 = reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
775 th_list->link (*this);
776 }
777
778 // Boost owner priority.
779 if ((boosted_prio_ > owner_->priority_inherited ()))
780 {
781 // ----- Enter uncritical section ---------------------------
782 scheduler::uncritical_section sucs;
783
784 owner_->priority_inherited (boosted_prio_);
785 // ----- Exit uncritical section ----------------------------
786 }
787
788#if defined(OS_TRACE_RTOS_MUTEX)
789 trace::printf ("%s() @%p %s boost %u by %p %s \n", __func__,
790 this, name (), boosted_prio_, th, th->name ());
791#endif
792
793 return EWOULDBLOCK;
794 }
795 }
796
797 // Block anyway.
798 return EWOULDBLOCK;
799 }
800
802 mutex::internal_unlock_ (thread* th)
803 {
804 if (!recoverable_)
805 {
806 return ENOTRECOVERABLE;
807 }
808
809 {
810 // ----- Enter critical section ---------------------------------------
811 scheduler::critical_section scs;
812
813 // Is the rightful owner?
814 if (owner_ == th)
815 {
816 if ((type_ == type::recursive) && (count_ > 1))
817 {
818#pragma GCC diagnostic push
819#if defined(__clang__)
820#pragma clang diagnostic ignored "-Wdeprecated-volatile"
821#elif defined(__GNUC__)
822#pragma GCC diagnostic ignored "-Wvolatile"
823#endif
824 // Decrement the recursion depth counter.
825 --count_;
826#pragma GCC diagnostic pop
827
828#if defined(OS_TRACE_RTOS_MUTEX)
829 trace::printf ("%s() @%p %s >%u\n", __func__, this, name (),
830 count_);
831#endif
832 return result::ok;
833 }
834
835#pragma GCC diagnostic push
836#if defined(__clang__)
837#pragma clang diagnostic ignored "-Wdeprecated-volatile"
838#elif defined(__GNUC__)
839#pragma GCC diagnostic ignored "-Wvolatile"
840#endif
841 --(owner_->acquired_mutexes_);
842#pragma GCC diagnostic pop
843
844 // Remove this mutex from the thread list; ineffective if
845 // not linked.
846 owner_links_.unlink ();
847
848 if (boosted_prio_ != thread::priority::none)
849 {
850 mutexes_list* thread_mutexes
851 = reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
852
853 if (thread_mutexes->empty ())
854 {
855 // If the owner thread has no more mutexes,
856 // clear the inherited priority,
857 // and the assigned priority will take precedence.
858 boosted_prio_ = thread::priority::none;
859 }
860 else
861 {
862 // If the owner thread acquired other mutexes too,
863 // compute the maximum boosted priority.
864 thread::priority_t max_prio = 0;
865#pragma GCC diagnostic push
866#if defined(__clang__)
867#elif defined(__GNUC__)
868#pragma GCC diagnostic ignored "-Waggregate-return"
869#endif
870 for (auto&& mx : *thread_mutexes)
871 {
872 if (mx.boosted_prio_ > max_prio)
873 {
874 max_prio = mx.boosted_prio_;
875 }
876 }
877#pragma GCC diagnostic pop
878 boosted_prio_ = max_prio;
879 }
880 // Delayed until end of critical section.
881 owner_->priority_inherited (boosted_prio_);
882 }
883
884 // Delayed until end of critical section.
885 list_.resume_one ();
886
887 // Finally release the mutex.
888 owner_ = nullptr;
889 count_ = 0;
890
891#if defined(OS_TRACE_RTOS_MUTEX)
892 trace::printf ("%s() @%p %s ULCK\n", __func__, this, name ());
893#endif
894
895 // POSIX: If a robust mutex whose owner died is unlocked without
896 // a call to consistent(), it shall be in a permanently
897 // unusable state and all attempts to lock the mutex
898 // shall fail with the error ENOTRECOVERABLE.
899
900 if (owner_dead_)
901 {
902 owner_dead_ = false;
903
904 if (!consistent_)
905 {
906 recoverable_ = false;
907 return ENOTRECOVERABLE;
908 }
909 }
910
911 return result::ok;
912 }
913
914 // Not owner, or not locked.
915 if (type_ == type::errorcheck || type_ == type::recursive
916 || robustness_ == robustness::robust)
917 {
918#if defined(OS_TRACE_RTOS_MUTEX)
919 trace::printf ("%s() EPERM @%p %s \n", __func__, this, name ());
920#endif
921 return EPERM;
922 }
923
924 // Normal no-robust mutexes owned by other threads have
925 // undefined behaviour.
926
927#if defined(OS_TRACE_RTOS_MUTEX)
928 trace::printf ("%s() ENOTRECOVERABLE @%p %s \n", __func__, this,
929 name ());
930#endif
931 return ENOTRECOVERABLE;
932 // ----- Exit critical section ----------------------------------------
933 }
934 }
935
936 // Called from thread termination, in a critical section.
937 void
938 mutex::internal_mark_owner_dead_ (void)
939 {
940 // May return error if not the rightful owner.
941 trace::printf ("%s() @%p %s\n", __func__, this, name ());
942
943 if (robustness_ == mutex::robustness::robust)
944 {
945 // If the owning thread of a robust mutex terminates
946 // while holding the mutex lock, the next thread that
947 // acquires the mutex may be notified about the termination
948 // by the return value EOWNERDEAD.
949 owner_dead_ = true;
950 consistent_ = false;
951 }
952 }
953
1002 result_t
1004 {
1005#if defined(OS_TRACE_RTOS_MUTEX)
1006 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1008#endif
1009
1010 // Don't call this from interrupt handlers.
1012 // Don't try to lock a non-recursive mutex again.
1013 os_assert_err (!scheduler::locked (), EPERM);
1014
1015 if (!recoverable_)
1016 {
1017 return ENOTRECOVERABLE;
1018 }
1019
1020#if defined(OS_USE_RTOS_PORT_MUTEX)
1021
1022 return port::mutex::lock (this);
1023
1024#else
1025
1026 thread& crt_thread = this_thread::thread ();
1027
1028 result_t res;
1029 {
1030 // ----- Enter critical section ---------------------------------------
1032
1033 res = internal_try_lock_ (&crt_thread);
1034 if (res != EWOULDBLOCK)
1035 {
1036 return res;
1037 }
1038 // ----- Exit critical section ----------------------------------------
1039 }
1040
1041 // Prepare a list node pointing to the current thread.
1042 // Do not worry for being on stack, it is temporarily linked to the
1043 // list and guaranteed to be removed before this function returns.
1044 internal::waiting_thread_node node{ crt_thread };
1045
1046 for (;;)
1047 {
1048 {
1049 // ----- Enter critical section -----------------------------------
1051
1052 res = internal_try_lock_ (&crt_thread);
1053 if (res != EWOULDBLOCK)
1054 {
1055 return res;
1056 }
1057
1058 {
1059 // ----- Enter critical section -----------------------------
1061
1062 // Add this thread to the mutex waiting list.
1063 scheduler::internal_link_node (list_, node);
1064 // state::suspended set in above link().
1065 // ----- Exit critical section ------------------------------
1066 }
1067 // ----- Exit critical section ------------------------------------
1068 }
1069
1071
1072 // Remove the thread from the semaphore waiting list,
1073 // if not already removed by unlock().
1074 scheduler::internal_unlink_node (node);
1075
1076 if (crt_thread.interrupted ())
1077 {
1078#if defined(OS_TRACE_RTOS_MUTEX)
1079 trace::printf ("%s() EINTR @%p %s\n", __func__, this, name ());
1080#endif
1081 return EINTR;
1082 }
1083 }
1084
1085 /* NOTREACHED */
1086 return ENOTRECOVERABLE;
1087
1088#endif
1089 }
1090
1125 result_t
1127 {
1128#if defined(OS_TRACE_RTOS_MUTEX)
1129 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1131#endif
1132
1133 // Don't call this from interrupt handlers.
1135
1136 if (!recoverable_)
1137 {
1138 return ENOTRECOVERABLE;
1139 }
1140
1141#if defined(OS_USE_RTOS_PORT_MUTEX)
1142
1143 return port::mutex::try_lock (this);
1144
1145#else
1146
1147 thread& crt_thread = this_thread::thread ();
1148
1149 {
1150 // ----- Enter critical section ---------------------------------------
1152
1153 return internal_try_lock_ (&crt_thread);
1154 // ----- Exit critical section ----------------------------------------
1155 }
1156
1157#endif
1158 }
1159
1204 result_t
1206 {
1207#if defined(OS_TRACE_RTOS_MUTEX)
1208#pragma GCC diagnostic push
1209#if defined(__clang__)
1210#elif defined(__GNUC__)
1211#pragma GCC diagnostic ignored "-Wuseless-cast"
1212#endif
1213 trace::printf ("%s(%u) @%p %s by %p %s\n", __func__,
1214 static_cast<unsigned int> (timeout), this, name (),
1216#pragma GCC diagnostic pop
1217#endif /* defined(OS_TRACE_RTOS_MUTEX) */
1218
1219 // Don't call this from interrupt handlers.
1221 // Don't try to lock a non-recursive mutex again.
1222 os_assert_err (!scheduler::locked (), EPERM);
1223
1224 if (!recoverable_)
1225 {
1226 return ENOTRECOVERABLE;
1227 }
1228
1229#if defined(OS_USE_RTOS_PORT_MUTEX)
1230
1231 return port::mutex::timed_lock (this, timeout);
1232
1233#else
1234
1235 thread& crt_thread = this_thread::thread ();
1236
1237 result_t res;
1238
1239 // Extra test before entering the loop, with its inherent weight.
1240 // Trade size for speed.
1241 {
1242 // ----- Enter critical section ---------------------------------------
1244
1245 res = internal_try_lock_ (&crt_thread);
1246 if (res != EWOULDBLOCK)
1247 {
1248 return res;
1249 }
1250 // ----- Exit critical section ----------------------------------------
1251 }
1252
1253 // Prepare a list node pointing to the current thread.
1254 // Do not worry for being on stack, it is temporarily linked to the
1255 // list and guaranteed to be removed before this function returns.
1256 internal::waiting_thread_node node{ crt_thread };
1257
1258 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
1259 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
1260
1261 // Prepare a timeout node pointing to the current thread.
1262 internal::timeout_thread_node timeout_node{ timeout_timestamp,
1263 crt_thread };
1264
1265 for (;;)
1266 {
1267 {
1268 // ----- Enter critical section -----------------------------------
1270
1271 res = internal_try_lock_ (&crt_thread);
1272 if (res != EWOULDBLOCK)
1273 {
1274 return res;
1275 }
1276
1277 {
1278 // ----- Enter critical section -----------------------------
1280
1281 // Add this thread to the mutex waiting list,
1282 // and the clock timeout list.
1283 scheduler::internal_link_node (list_, node, clock_list,
1284 timeout_node);
1285 // state::suspended set in above link().
1286 // ----- Exit critical section ------------------------------
1287 }
1288 // ----- Exit critical section ------------------------------------
1289 }
1290
1292
1293 // Remove the thread from the semaphore waiting list,
1294 // if not already removed by unlock() and from the clock
1295 // timeout list, if not already removed by the timer.
1296 scheduler::internal_unlink_node (node, timeout_node);
1297
1298 res = result::ok;
1299
1300 if (crt_thread.interrupted ())
1301 {
1302#if defined(OS_TRACE_RTOS_MUTEX)
1303 trace::printf ("%s() EINTR @%p %s \n", __func__, this, name ());
1304#endif
1305 res = EINTR;
1306 }
1307 else if (clock_->steady_now () >= timeout_timestamp)
1308 {
1309#if defined(OS_TRACE_RTOS_MUTEX)
1310 trace::printf ("%s() ETIMEDOUT @%p %s \n", __func__, this,
1311 name ());
1312#endif
1313 res = ETIMEDOUT;
1314 }
1315 if (res != result::ok)
1316 {
1317 if (boosted_prio_ != thread::priority::none)
1318 {
1319 // If the priority was boosted, it must be restored
1320 // to the highest priority of the waiting threads, if any.
1321
1323
1324#pragma GCC diagnostic push
1325#if defined(__clang__)
1326#elif defined(__GNUC__)
1327#pragma GCC diagnostic ignored "-Waggregate-return"
1328#endif
1329 for (auto&& th : list_)
1330 {
1331 thread::priority_t prio = th.priority ();
1332 if (prio > max_prio)
1333 {
1334 max_prio = prio;
1335 }
1336 }
1337#pragma GCC diagnostic pop
1338
1339 if (max_prio != thread::priority::none)
1340 {
1341 boosted_prio_ = max_prio;
1342 owner_->priority (boosted_prio_);
1343 }
1344 }
1345 return res;
1346 }
1347 }
1348
1349 /* NOTREACHED */
1350 return ENOTRECOVERABLE;
1351
1352#endif
1353 }
1354
1378 result_t
1380 {
1381#if defined(OS_TRACE_RTOS_MUTEX)
1382 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1384#endif
1385
1386 // Don't call this from interrupt handlers.
1388
1389#if defined(OS_USE_RTOS_PORT_MUTEX)
1390
1391 return port::mutex::unlock (this);
1392
1393#else
1394
1395 thread* crt_thread = &this_thread::thread ();
1396
1397 return internal_unlock_ (crt_thread);
1398
1399#endif
1400 }
1401
1418 {
1419#if defined(OS_TRACE_RTOS_MUTEX)
1420 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1421#endif
1422
1423 // Don't call this from interrupt handlers.
1424 assert (!interrupts::in_handler_mode ());
1425
1426#if defined(OS_USE_RTOS_PORT_MUTEX)
1427
1428 return port::mutex::prio_ceiling (this);
1429
1430#else
1431
1432 return prio_ceiling_;
1433
1434#endif
1435 }
1436
1460 result_t
1462 thread::priority_t* old_prio_ceiling)
1463 {
1464#if defined(OS_TRACE_RTOS_MUTEX)
1465 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1466#endif
1467
1468 // Don't call this from interrupt handlers.
1470
1471#if defined(OS_USE_RTOS_PORT_MUTEX)
1472
1473 return port::mutex::prio_ceiling (this, prio_ceiling, old_prio_ceiling);
1474
1475#else
1476
1477 // TODO: lock() must not adhere to the priority protocol.
1478 result_t res = lock ();
1479 if (res != result::ok)
1480 {
1481 return res;
1482 }
1483
1484 if (old_prio_ceiling != nullptr)
1485 {
1486 *old_prio_ceiling = prio_ceiling_;
1487 }
1488
1489 prio_ceiling_ = prio_ceiling;
1490
1491 unlock ();
1492
1493 return result::ok;
1494
1495#endif
1496 }
1497
1529 result_t
1531 {
1532#if defined(OS_TRACE_RTOS_MUTEX)
1533 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1534#endif
1535
1536 // Don't call this from interrupt handlers.
1538 // Don't call this for non-robust mutexes.
1539 os_assert_err (robustness_ == robustness::robust, EINVAL);
1540 // Don't call it if already consistent.
1541 os_assert_err (!consistent_, EINVAL);
1542
1543#if defined(OS_USE_RTOS_PORT_MUTEX)
1544
1545 return port::mutex::consistent (this);
1546
1547#else
1548
1549 // Update status to consistent.
1550 consistent_ = true;
1551 return result::ok;
1552
1553#endif
1554 }
1555
1566 result_t
1568 {
1569#if defined(OS_TRACE_RTOS_MUTEX)
1570 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1571#endif
1572
1573 // Don't call this from interrupt handlers.
1575
1576 {
1577 // ----- Enter critical section ---------------------------------------
1579
1580 internal_init_ ();
1581 return result::ok;
1582 // ----- Exit critical section ----------------------------------------
1583 }
1584 }
1585
1586 // ========================================================================
1587
1604 // ------------------------------------------------------------------------
1605 } /* namespace rtos */
1606} /* namespace os */
1607
1608// ----------------------------------------------------------------------------
rtos::clock * clock
Attribute with the address of the clock to be used for timeouts.
Definition os-decls.h:612
Ordered list of time stamp nodes.
Definition os-lists.h:666
const char * name(void) const
Get object name.
Definition os-decls.h:753
Double linked list node, with time stamp and thread.
Definition os-lists.h:220
Double linked list node, with thread reference.
Definition os-lists.h:59
Interrupts critical section RAII helper.
Definition os-sched.h:502
Mutex attributes.
Definition os-mutex.h:202
thread::priority_t mx_priority_ceiling
Attribute with the mutex priority ceiling.
Definition os-mutex.h:258
POSIX compliant mutex.
Definition os-mutex.h:52
result_t reset(void)
Reset the mutex.
result_t lock(void)
Lock/acquire the mutex.
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:470
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:570
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:171
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:251
bool interrupted(void)
Check if interrupted.
Definition os-thread.h:2373
List of intrusive nodes.
Definition lists.h:690
Standard thread.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:78
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:88
clock_systick sysclock
The system clock object instance.
static const attributes_recursive initializer_recursive
Default recursive mutex initialiser.
Definition os-mutex.h:341
static const attributes initializer_normal
Default normal mutex initialiser.
Definition os-mutex.h:292
uint8_t priority_t
Type of variables holding thread priorities.
Definition os-thread.h:271
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1101
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:179
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:858
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:328
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:95
System namespace.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
Definition os-decls.h:1122
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1101
Single file µOS++ RTOS definitions.
@ max_
Maximum value, for validation purposes.
Definition os-mutex.h:95
@ inherit
Inherit priority from highest priority thread.
Definition os-mutex.h:80
@ protect
Execute at the highest priority.
Definition os-mutex.h:85
@ max_
Maximum value, for validation purposes.
Definition os-mutex.h:135
@ robust
Enhanced robustness at thread termination.
Definition os-mutex.h:125
@ max_
Maximum value, for validation purposes.
Definition os-mutex.h:178
@ normal
Normal mutex behaviour.
Definition os-mutex.h:160
@ errorcheck
Check mutex behaviour.
Definition os-mutex.h:164
@ recursive
Recursive mutex behaviour.
Definition os-mutex.h:168