µ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-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#if defined(OS_USE_OS_APP_CONFIG_H)
14#include <cmsis-plus/os-app-config.h>
15#endif
16
17#include <cmsis-plus/rtos/os.h>
18
19// ----------------------------------------------------------------------------
20
21#if defined(__clang__)
22#pragma clang diagnostic ignored "-Wc++98-compat"
23#endif
24
25// ----------------------------------------------------------------------------
26
27namespace os
28{
29 namespace rtos
30 {
31 // ------------------------------------------------------------------------
32
283 const mutex::attributes mutex::initializer_normal;
284
289 const mutex::attributes_recursive mutex::initializer_recursive;
290
291 // ------------------------------------------------------------------------
292
294 mutex, utils::double_list_links, &mutex::owner_links_>;
295
296 // ------------------------------------------------------------------------
297
430 mutex::mutex (const attributes& attr) :
431 mutex
432 { nullptr, attr }
433 {
434 }
435
466 mutex::mutex (const char* name, const attributes& attr) :
467 object_named_system
468 { name }, //
469 type_ (attr.mx_type), //
470 protocol_ (attr.mx_protocol), //
471 robustness_ (attr.mx_robustness), //
472 max_count_ ((attr.mx_type == type::recursive) ? attr.mx_max_count : 1)
473 {
474#if defined(OS_TRACE_RTOS_MUTEX)
475 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
476#endif
477
478 // Don't call this from interrupt handlers.
480
481 os_assert_throw(type_ <= type::max_, EINVAL);
482 os_assert_throw(protocol_ <= protocol::max_, EINVAL);
483 os_assert_throw(robustness_ <= robustness::max_, EINVAL);
484
485#if !defined(OS_USE_RTOS_PORT_MUTEX)
486 clock_ = attr.clock != nullptr ? attr.clock : &sysclock;
487#endif
488
489 os_assert_throw(attr.mx_priority_ceiling >= thread::priority::lowest,
490 EINVAL);
491 os_assert_throw(attr.mx_priority_ceiling <= thread::priority::highest,
492 EINVAL);
493
494 initial_prio_ceiling_ = attr.mx_priority_ceiling;
495 prio_ceiling_ = attr.mx_priority_ceiling;
496
497#if defined(OS_USE_RTOS_PORT_MUTEX)
498
499 count_ = 0;
500 port::mutex::create (this);
501
502#else
503
504 internal_init_ ();
505
506#endif
507 }
508
527 {
528#if defined(OS_TRACE_RTOS_MUTEX)
529 trace::printf ("%s() @%p %s\n", __func__, this, name ());
530#endif
531
532#if defined(OS_USE_RTOS_PORT_MUTEX)
533
534 port::mutex::destroy (this);
535
536#else
537
538 // The mutex must have no owner (must have been unlocked).
539 assert(owner_ == nullptr);
540 // There must be no threads waiting for this mutex.
541 assert(list_.empty ());
542
543#endif
544 }
545
550 void
551 mutex::internal_init_ (void)
552 {
553 owner_ = nullptr;
554 owner_links_.unlink ();
555 count_ = 0;
556 prio_ceiling_ = initial_prio_ceiling_;
557 boosted_prio_ = thread::priority::none;
558 owner_dead_ = false;
559 consistent_ = true;
560 recoverable_ = true;
561
562#if !defined(OS_USE_RTOS_PORT_MUTEX)
563
564 // Wake-up all threads, if any.
565 // Need not be inside the critical section,
566 // the list is protected by inner `resume_one()`.
567 list_.resume_all ();
568
569#endif
570 }
571
572 /*
573 * Internal function.
574 * Should be called from a scheduler critical section.
575 */
577 mutex::internal_try_lock_ (/* class */ thread* th)
578 {
579 // Save the initial owner for later protocol tests.
580 thread* saved_owner = owner_;
581
582 // First lock.
583 if (owner_ == nullptr)
584 {
585 // If the mutex has no owner, own it.
586 owner_ = th;
587
588 // For recursive mutexes, initialise counter.
589 count_ = 1;
590
591 // Add mutex to the thread list.
592 mutexes_list* th_list =
593 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
594 th_list->link (*this);
595
596#pragma GCC diagnostic push
597#if defined(__clang__)
598#pragma clang diagnostic ignored "-Wdeprecated-volatile"
599#elif defined(__GNUC__)
600#pragma GCC diagnostic ignored "-Wvolatile"
601#endif
602 // Count the number of mutexes acquired by the thread.
603 ++(owner_->acquired_mutexes_);
604#pragma GCC diagnostic pop
605
606 if (protocol_ == protocol::protect)
607 {
608 if (th->priority () > prio_ceiling_)
609 {
610 // No need to keep the lock.
611 owner_ = nullptr;
612
613 // Prio ceiling must be at least the priority of the
614 // highest priority thread.
615 return EINVAL;
616 }
617
618 // POSIX: When a thread owns one or more mutexes
619 // initialised with the mutex::protocol::protect protocol,
620 // it shall execute at the higher of its priority or the
621 // highest of the priority ceilings of all the mutexes
622 // owned by this thread and initialised with this
623 // attribute, regardless of whether other threads are
624 // blocked on any of these robust mutexes or not.
625
626 // Boost priority.
627 boosted_prio_ = prio_ceiling_;
628 if (boosted_prio_ > owner_->priority_inherited ())
629 {
630 // ----- Enter uncritical section ---------------------------
631 scheduler::uncritical_section sucs;
632
633 owner_->priority_inherited (boosted_prio_);
634 // ----- Exit uncritical section ----------------------------
635 }
636 }
637
638#if defined(OS_TRACE_RTOS_MUTEX)
639 trace::printf ("%s() @%p %s by %p %s LCK\n", __func__, this, name (),
640 th, th->name ());
641#endif
642 // If the owning thread of a robust mutex terminates while
643 // holding the mutex lock, the next thread that acquires the
644 // mutex may be notified about the termination by the return
645 // value EOWNERDEAD.
646 if (owner_dead_)
647 {
648 // TODO: decide if the lock must be preserved.
649 return EOWNERDEAD;
650 }
651 return result::ok;
652 }
653
654 // Relock? (lock by the same thread).
655 if (saved_owner == th)
656 {
657 // The mutex was requested again by the same thread.
658 if (type_ == type::recursive)
659 {
660 if (count_ >= max_count_)
661 {
662 // The recursive mutex reached its limit.
663#if defined(OS_TRACE_RTOS_MUTEX)
664 trace::printf ("%s() @%p %s EAGAIN\n", __func__, this,
665 name ());
666#endif
667 return EAGAIN;
668 }
669
670#pragma GCC diagnostic push
671#if defined(__clang__)
672#pragma clang diagnostic ignored "-Wdeprecated-volatile"
673#elif defined(__GNUC__)
674#pragma GCC diagnostic ignored "-Wvolatile"
675#endif
676 // Increment the recursion depth counter.
677 ++count_;
678#pragma GCC diagnostic pop
679
680#if defined(OS_TRACE_RTOS_MUTEX)
681 trace::printf ("%s() @%p %s by %p %s >%u\n", __func__, this,
682 name (), th, th->name (), count_);
683#endif
684 return result::ok;
685 }
686 else if (type_ == type::errorcheck)
687 {
688 // Errorcheck mutexes do not block, but return an error.
689#if defined(OS_TRACE_RTOS_MUTEX)
690 trace::printf ("%s() @%p %s EDEADLK\n", __func__, this, name ());
691#endif
692 return EDEADLK;
693 }
694 else if (type_ == type::normal)
695 {
696#if defined(OS_TRACE_RTOS_MUTEX)
697 trace::printf ("%s() @%p %s deadlock\n", __func__, this, name ());
698#endif
699 return EWOULDBLOCK;
700 }
701
702 return EWOULDBLOCK;
703 }
704 else
705 {
706 // Try to lock when not owner (another thread requested the mutex).
707
708 // POSIX: When a thread makes a call to mutex::lock(), the mutex was
709 // initialised with the protocol attribute having the value
710 // mutex::protocol::inherit, when the calling thread is blocked
711 // because the mutex is owned by another thread, that owner thread
712 // shall inherit the priority level of the calling thread as long
713 // as it continues to own the mutex. The implementation shall
714 // update its execution priority to the maximum of its assigned
715 // priority and all its inherited priorities.
716 // Furthermore, if this owner thread itself becomes blocked on
717 // another mutex with the protocol attribute having the value
718 // mutex::protocol::inherit, the same priority inheritance effect
719 // shall be propagated to this other owner thread, in a recursive
720 // manner.
721 if (protocol_ == protocol::inherit)
722 {
723 thread::priority_t prio = th->priority ();
724 boosted_prio_ = prio;
725
726 if (owner_links_.unlinked ())
727 {
728 mutexes_list* th_list =
729 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
730 th_list->link (*this);
731 }
732
733 // Boost owner priority.
734 if ((boosted_prio_ > owner_->priority_inherited ()))
735 {
736 // ----- Enter uncritical section ---------------------------
737 scheduler::uncritical_section sucs;
738
739 owner_->priority_inherited (boosted_prio_);
740 // ----- Exit uncritical section ----------------------------
741 }
742
743#if defined(OS_TRACE_RTOS_MUTEX)
744 trace::printf ("%s() @%p %s boost %u by %p %s \n", __func__, this,
745 name (), boosted_prio_, th, th->name ());
746#endif
747
748 return EWOULDBLOCK;
749 }
750 }
751
752 // Block anyway.
753 return EWOULDBLOCK;
754 }
755
757 mutex::internal_unlock_ (thread* th)
758 {
759 if (!recoverable_)
760 {
761 return ENOTRECOVERABLE;
762 }
763
764 {
765 // ----- Enter critical section -------------------------------------
766 scheduler::critical_section scs;
767
768 // Is the rightful owner?
769 if (owner_ == th)
770 {
771 if ((type_ == type::recursive) && (count_ > 1))
772 {
773#pragma GCC diagnostic push
774#if defined(__clang__)
775#pragma clang diagnostic ignored "-Wdeprecated-volatile"
776#elif defined(__GNUC__)
777#pragma GCC diagnostic ignored "-Wvolatile"
778#endif
779 // Decrement the recursion depth counter.
780 --count_;
781#pragma GCC diagnostic pop
782
783#if defined(OS_TRACE_RTOS_MUTEX)
784 trace::printf ("%s() @%p %s >%u\n", __func__, this, name (),
785 count_);
786#endif
787 return result::ok;
788 }
789
790#pragma GCC diagnostic push
791#if defined(__clang__)
792#pragma clang diagnostic ignored "-Wdeprecated-volatile"
793#elif defined(__GNUC__)
794#pragma GCC diagnostic ignored "-Wvolatile"
795#endif
796 --(owner_->acquired_mutexes_);
797#pragma GCC diagnostic pop
798
799 // Remove this mutex from the thread list; ineffective if
800 // not linked.
801 owner_links_.unlink ();
802
803 if (boosted_prio_ != thread::priority::none)
804 {
805 mutexes_list* thread_mutexes =
806 reinterpret_cast<mutexes_list*> (&owner_->mutexes_);
807
808 if (thread_mutexes->empty ())
809 {
810 // If the owner thread has no more mutexes,
811 // clear the inherited priority,
812 // and the assigned priority will take precedence.
813 boosted_prio_ = thread::priority::none;
814 }
815 else
816 {
817 // If the owner thread acquired other mutexes too,
818 // compute the maximum boosted priority.
819 thread::priority_t max_prio = 0;
820#pragma GCC diagnostic push
821#if defined(__clang__)
822#elif defined(__GNUC__)
823#pragma GCC diagnostic ignored "-Waggregate-return"
824#endif
825 for (auto&& mx : *thread_mutexes)
826 {
827 if (mx.boosted_prio_ > max_prio)
828 {
829 max_prio = mx.boosted_prio_;
830 }
831 }
832#pragma GCC diagnostic pop
833 boosted_prio_ = max_prio;
834 }
835 // Delayed until end of critical section.
836 owner_->priority_inherited (boosted_prio_);
837 }
838
839 // Delayed until end of critical section.
840 list_.resume_one ();
841
842 // Finally release the mutex.
843 owner_ = nullptr;
844 count_ = 0;
845
846#if defined(OS_TRACE_RTOS_MUTEX)
847 trace::printf ("%s() @%p %s ULCK\n", __func__, this, name ());
848#endif
849
850 // POSIX: If a robust mutex whose owner died is unlocked without
851 // a call to consistent(), it shall be in a permanently
852 // unusable state and all attempts to lock the mutex
853 // shall fail with the error ENOTRECOVERABLE.
854
855 if (owner_dead_)
856 {
857 owner_dead_ = false;
858
859 if (!consistent_)
860 {
861 recoverable_ = false;
862 return ENOTRECOVERABLE;
863 }
864 }
865
866 return result::ok;
867 }
868
869 // Not owner, or not locked.
870 if (type_ == type::errorcheck || type_ == type::recursive
871 || robustness_ == robustness::robust)
872 {
873#if defined(OS_TRACE_RTOS_MUTEX)
874 trace::printf ("%s() EPERM @%p %s \n", __func__, this, name ());
875#endif
876 return EPERM;
877 }
878
879 // Normal no-robust mutexes owned by other threads have
880 // undefined behaviour.
881
882#if defined(OS_TRACE_RTOS_MUTEX)
883 trace::printf ("%s() ENOTRECOVERABLE @%p %s \n", __func__, this,
884 name ());
885#endif
886 return ENOTRECOVERABLE;
887 // ----- Exit critical section --------------------------------------
888 }
889 }
890
891 // Called from thread termination, in a critical section.
892 void
893 mutex::internal_mark_owner_dead_ (void)
894 {
895 // May return error if not the rightful owner.
896 trace::printf ("%s() @%p %s\n", __func__, this, name ());
897
898 if (robustness_ == mutex::robustness::robust)
899 {
900 // If the owning thread of a robust mutex terminates
901 // while holding the mutex lock, the next thread that
902 // acquires the mutex may be notified about the termination
903 // by the return value EOWNERDEAD.
904 owner_dead_ = true;
905 consistent_ = false;
906 }
907 }
908
956 {
957#if defined(OS_TRACE_RTOS_MUTEX)
958 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
960#endif
961
962 // Don't call this from interrupt handlers.
964 // Don't try to lock a non-recursive mutex again.
966
967 if (!recoverable_)
968 {
969 return ENOTRECOVERABLE;
970 }
971
972#if defined(OS_USE_RTOS_PORT_MUTEX)
973
974 return port::mutex::lock (this);
975
976#else
977
978 thread& crt_thread = this_thread::thread ();
979
980 result_t res;
981 {
982 // ----- Enter critical section -------------------------------------
984
985 res = internal_try_lock_ (&crt_thread);
986 if (res != EWOULDBLOCK)
987 {
988 return res;
989 }
990 // ----- Exit critical section --------------------------------------
991 }
992
993 // Prepare a list node pointing to the current thread.
994 // Do not worry for being on stack, it is temporarily linked to the
995 // list and guaranteed to be removed before this function returns.
997 { crt_thread };
998
999 for (;;)
1000 {
1001 {
1002 // ----- Enter critical section ---------------------------------
1004
1005 res = internal_try_lock_ (&crt_thread);
1006 if (res != EWOULDBLOCK)
1007 {
1008 return res;
1009 }
1010
1011 {
1012 // ----- Enter critical section -----------------------------
1014
1015 // Add this thread to the mutex waiting list.
1016 scheduler::internal_link_node (list_, node);
1017 // state::suspended set in above link().
1018 // ----- Exit critical section ------------------------------
1019 }
1020 // ----- Exit critical section ----------------------------------
1021 }
1022
1024
1025 // Remove the thread from the semaphore waiting list,
1026 // if not already removed by unlock().
1027 scheduler::internal_unlink_node (node);
1028
1029 if (crt_thread.interrupted ())
1030 {
1031#if defined(OS_TRACE_RTOS_MUTEX)
1032 trace::printf ("%s() EINTR @%p %s\n", __func__, this, name ());
1033#endif
1034 return EINTR;
1035 }
1036 }
1037
1038 /* NOTREACHED */
1039 return ENOTRECOVERABLE;
1040
1041#endif
1042 }
1043
1075 result_t
1077 {
1078#if defined(OS_TRACE_RTOS_MUTEX)
1079 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1081#endif
1082
1083 // Don't call this from interrupt handlers.
1085
1086 if (!recoverable_)
1087 {
1088 return ENOTRECOVERABLE;
1089 }
1090
1091#if defined(OS_USE_RTOS_PORT_MUTEX)
1092
1093 return port::mutex::try_lock (this);
1094
1095#else
1096
1097 thread& crt_thread = this_thread::thread ();
1098
1099 {
1100 // ----- Enter critical section -------------------------------------
1102
1103 return internal_try_lock_ (&crt_thread);
1104 // ----- Exit critical section --------------------------------------
1105 }
1106
1107#endif
1108 }
1109
1151 result_t
1153 {
1154#if defined(OS_TRACE_RTOS_MUTEX)
1155#pragma GCC diagnostic push
1156#if defined(__clang__)
1157#elif defined(__GNUC__)
1158#pragma GCC diagnostic ignored "-Wuseless-cast"
1159#endif
1160 trace::printf ("%s(%u) @%p %s by %p %s\n", __func__,
1161 static_cast<unsigned int> (timeout), this, name (),
1163#pragma GCC diagnostic pop
1164#endif /* defined(OS_TRACE_RTOS_MUTEX) */
1165
1166 // Don't call this from interrupt handlers.
1168 // Don't try to lock a non-recursive mutex again.
1169 os_assert_err(!scheduler::locked (), EPERM);
1170
1171 if (!recoverable_)
1172 {
1173 return ENOTRECOVERABLE;
1174 }
1175
1176#if defined(OS_USE_RTOS_PORT_MUTEX)
1177
1178 return port::mutex::timed_lock (this, timeout);
1179
1180#else
1181
1182 thread& crt_thread = this_thread::thread ();
1183
1184 result_t res;
1185
1186 // Extra test before entering the loop, with its inherent weight.
1187 // Trade size for speed.
1188 {
1189 // ----- Enter critical section -------------------------------------
1191
1192 res = internal_try_lock_ (&crt_thread);
1193 if (res != EWOULDBLOCK)
1194 {
1195 return res;
1196 }
1197 // ----- Exit critical section --------------------------------------
1198 }
1199
1200 // Prepare a list node pointing to the current thread.
1201 // Do not worry for being on stack, it is temporarily linked to the
1202 // list and guaranteed to be removed before this function returns.
1204 { crt_thread };
1205
1206 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
1207 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
1208
1209 // Prepare a timeout node pointing to the current thread.
1211 { timeout_timestamp, crt_thread };
1212
1213 for (;;)
1214 {
1215 {
1216 // ----- Enter critical section ---------------------------------
1218
1219 res = internal_try_lock_ (&crt_thread);
1220 if (res != EWOULDBLOCK)
1221 {
1222 return res;
1223 }
1224
1225 {
1226 // ----- Enter critical section -----------------------------
1228
1229 // Add this thread to the mutex waiting list,
1230 // and the clock timeout list.
1231 scheduler::internal_link_node (list_, node, clock_list,
1232 timeout_node);
1233 // state::suspended set in above link().
1234 // ----- Exit critical section ------------------------------
1235 }
1236 // ----- Exit critical section ----------------------------------
1237 }
1238
1240
1241 // Remove the thread from the semaphore waiting list,
1242 // if not already removed by unlock() and from the clock
1243 // timeout list, if not already removed by the timer.
1244 scheduler::internal_unlink_node (node, timeout_node);
1245
1246 res = result::ok;
1247
1248 if (crt_thread.interrupted ())
1249 {
1250#if defined(OS_TRACE_RTOS_MUTEX)
1251 trace::printf ("%s() EINTR @%p %s \n", __func__, this, name ());
1252#endif
1253 res = EINTR;
1254 }
1255 else if (clock_->steady_now () >= timeout_timestamp)
1256 {
1257#if defined(OS_TRACE_RTOS_MUTEX)
1258 trace::printf ("%s() ETIMEDOUT @%p %s \n", __func__, this,
1259 name ());
1260#endif
1261 res = ETIMEDOUT;
1262 }
1263 if (res != result::ok)
1264 {
1265 if (boosted_prio_ != thread::priority::none)
1266 {
1267 // If the priority was boosted, it must be restored
1268 // to the highest priority of the waiting threads, if any.
1269
1271
1272#pragma GCC diagnostic push
1273#if defined(__clang__)
1274#elif defined(__GNUC__)
1275#pragma GCC diagnostic ignored "-Waggregate-return"
1276#endif
1277 for (auto&& th : list_)
1278 {
1279 thread::priority_t prio = th.priority ();
1280 if (prio > max_prio)
1281 {
1282 max_prio = prio;
1283 }
1284 }
1285#pragma GCC diagnostic pop
1286
1287 if (max_prio != thread::priority::none)
1288 {
1289 boosted_prio_ = max_prio;
1290 owner_->priority (boosted_prio_);
1291 }
1292 }
1293 return res;
1294 }
1295 }
1296
1297 /* NOTREACHED */
1298 return ENOTRECOVERABLE;
1299
1300#endif
1301 }
1302
1323 result_t
1325 {
1326#if defined(OS_TRACE_RTOS_MUTEX)
1327 trace::printf ("%s() @%p %s by %p %s\n", __func__, this, name (),
1329#endif
1330
1331 // Don't call this from interrupt handlers.
1333
1334#if defined(OS_USE_RTOS_PORT_MUTEX)
1335
1336 return port::mutex::unlock (this);
1337
1338#else
1339
1340 thread* crt_thread = &this_thread::thread ();
1341
1342 return internal_unlock_ (crt_thread);
1343
1344#endif
1345 }
1346
1360 {
1361#if defined(OS_TRACE_RTOS_MUTEX)
1362 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1363#endif
1364
1365 // Don't call this from interrupt handlers.
1366 assert(!interrupts::in_handler_mode ());
1367
1368#if defined(OS_USE_RTOS_PORT_MUTEX)
1369
1370 return port::mutex::prio_ceiling (this);
1371
1372#else
1373
1374 return prio_ceiling_;
1375
1376#endif
1377 }
1378
1399 result_t
1401 thread::priority_t* old_prio_ceiling)
1402 {
1403#if defined(OS_TRACE_RTOS_MUTEX)
1404 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1405#endif
1406
1407 // Don't call this from interrupt handlers.
1409
1410#if defined(OS_USE_RTOS_PORT_MUTEX)
1411
1412 return port::mutex::prio_ceiling (this, prio_ceiling, old_prio_ceiling);
1413
1414#else
1415
1416 // TODO: lock() must not adhere to the priority protocol.
1417 result_t res = lock ();
1418 if (res != result::ok)
1419 {
1420 return res;
1421 }
1422
1423 if (old_prio_ceiling != nullptr)
1424 {
1425 *old_prio_ceiling = prio_ceiling_;
1426 }
1427
1428 prio_ceiling_ = prio_ceiling;
1429
1430 unlock ();
1431
1432 return result::ok;
1433
1434#endif
1435 }
1436
1465 result_t
1467 {
1468#if defined(OS_TRACE_RTOS_MUTEX)
1469 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1470#endif
1471
1472 // Don't call this from interrupt handlers.
1474 // Don't call this for non-robust mutexes.
1475 os_assert_err(robustness_ == robustness::robust, EINVAL);
1476 // Don't call it if already consistent.
1477 os_assert_err(!consistent_, EINVAL);
1478
1479#if defined(OS_USE_RTOS_PORT_MUTEX)
1480
1481 return port::mutex::consistent (this);
1482
1483#else
1484
1485 // Update status to consistent.
1486 consistent_ = true;
1487 return result::ok;
1488
1489#endif
1490 }
1491
1502 result_t
1504 {
1505#if defined(OS_TRACE_RTOS_MUTEX)
1506 trace::printf ("%s() @%p %s\n", __func__, this, name ());
1507#endif
1508
1509 // Don't call this from interrupt handlers.
1511
1512 {
1513 // ----- Enter critical section -------------------------------------
1515
1516 internal_init_ ();
1517 return result::ok;
1518 // ----- Exit critical section --------------------------------------
1519 }
1520
1521 }
1522
1523 // ==========================================================================
1524
1540 // --------------------------------------------------------------------------
1541 } /* namespace rtos */
1542} /* namespace os */
1543
1544// ----------------------------------------------------------------------------
Ordered list of time stamp nodes.
Definition os-lists.h:671
const char * name(void) const
Get object name.
Definition os-decls.h:759
Double linked list node, with time stamp and thread.
Definition os-lists.h:223
Double linked list node, with thread reference.
Definition os-lists.h:60
Interrupts critical section RAII helper.
Definition os-sched.h:498
Mutex attributes.
Definition os-mutex.h:207
POSIX compliant mutex.
Definition os-mutex.h:53
result_t reset(void)
Reset the mutex.
result_t lock(void)
Lock/acquire the mutex.
Definition os-mutex.cpp:955
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:430
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:526
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:170
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:250
bool interrupted(void)
Check if interrupted.
Definition os-thread.h:2367
List of intrusive nodes.
Definition lists.h:705
Standard thread.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:60
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:76
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:85
clock_systick sysclock
The system clock object instance.
static const attributes_recursive initializer_recursive
Default recursive mutex initialiser.
Definition os-mutex.h:350
static const attributes initializer_normal
Default normal mutex initialiser.
Definition os-mutex.h:301
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:1108
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:181
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:856
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:294
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:96
System namespace.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
Definition os-decls.h:1130
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1115
Single file µOS++ RTOS definitions.
@ inherit
Inherit priority from highest priority thread.
Definition os-mutex.h:83
@ protect
Execute at the highest priority.
Definition os-mutex.h:88
@ robust
Enhanced robustness at thread termination.
Definition os-mutex.h:129
@ normal
Normal mutex behaviour.
Definition os-mutex.h:165
@ errorcheck
Check mutex behaviour.
Definition os-mutex.h:169
@ recursive
Recursive mutex behaviour.
Definition os-mutex.h:173