µ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::rtos::semaphore_counting Class Reference

POSIX compliant counting semaphore. More...

#include <cmsis-plus/rtos/os.h>

+ Inheritance diagram for os::rtos::semaphore_counting:

Public Types

using count_t = int16_t
 Type of semaphore counter storage.
 

Public Member Functions

Constructors & Destructor
 semaphore_counting (const count_t max_value, const count_t initial_value)
 Construct a binary semaphore object instance.
 
 semaphore_counting (const char *name, const count_t max_value, const count_t initial_value)
 Construct a named binary semaphore object instance.
 
 ~semaphore_counting ()
 Destruct the semaphore object instance.
 
Operators
bool operator== (const semaphore_counting &rhs) const
 Compare semaphores.
 
Operators
bool operator== (const semaphore &rhs) const
 Compare semaphores.
 
Public Member Functions
result_t post (void)
 Post (unlock) the semaphore.
 
result_t wait (void)
 Lock the semaphore, possibly waiting.
 
result_t try_wait (void)
 Try to lock the semaphore.
 
result_t timed_wait (clock::duration_t timeout)
 Timed wait to lock the semaphore.
 
count_t value (void) const
 Get the semaphore count value.
 
result_t reset (void)
 Reset the semaphore.
 
count_t initial_value (void) const
 Get the semaphore initial count value.
 
count_t max_value (void) const
 Get the semaphore maximum count value.
 
Public Member Functions
const char * name (void) const
 Get object name.
 

Static Public Member Functions

Operators
static void * operator new (std::size_t bytes)
 Allocate space for a new object instance using the RTOS system allocator.
 
static void * operator new (std::size_t bytes, void *ptr)
 Emplace a new object instance.
 
static void * operator new[] (std::size_t bytes)
 Allocate space for an array of new object instances using the RTOS system allocator.
 
static void * operator new[] (std::size_t bytes, void *ptr)
 Emplace an array of new object instances.
 
static void operator delete (void *ptr, std::size_t bytes)
 Deallocate the dynamically allocated object instance. using the RTOS system allocator.
 
static void operator delete[] (void *ptr, std::size_t bytes)
 Deallocate the dynamically allocated array of object. instances using the RTOS system allocator.
 

Static Public Attributes

static const attributes_binary initializer_binary { 0 }
 Default binary semaphore initialiser.
 
static constexpr count_t max_count_value = 0x7FFF
 Maximum semaphore value.
 

Detailed Description

Definition at line 588 of file os-semaphore.h.

Constructor & Destructor Documentation

◆ semaphore_counting() [1/2]

os::rtos::semaphore_counting::semaphore_counting ( const count_t  max_value,
const count_t  initial_value 
)
inline
Parameters
[in]max_valueMaximum count value.
[in]initial_valueInitial count value; 0 if missing.

This constructor shall initialise a counting semaphore object with the given max_value and initial_value. Upon successful initialisation, the state of the semaphore object shall become initialised.

Only the semaphore object itself may be used for performing synchronisation. It is not allowed to make copies of semaphore objects.

POSIX compatibility
Inspired by sem_init() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 882 of file os-semaphore.h.

884 : semaphore{ nullptr, max_value, initial_value }
885 {
886 }
semaphore(const attributes &attr=initializer_binary)
Construct a semaphore object instance.
count_t max_value(void) const
Get the semaphore maximum count value.
count_t initial_value(void) const
Get the semaphore initial count value.

◆ semaphore_counting() [2/2]

os::rtos::semaphore_counting::semaphore_counting ( const char *  name,
const count_t  max_value,
const count_t  initial_value 
)
inline
Parameters
[in]namePointer to name.
[in]max_valueMaximum count value.
[in]initial_valueInitial count value; 0 if missing.

This constructor shall initialise a named counting semaphore object with the given max_value and initial_value. Upon successful initialisation, the state of the semaphore object shall become initialised.

Only the semaphore object itself may be used for performing synchronisation. It is not allowed to make copies of semaphore objects.

POSIX compatibility
Inspired by sem_init() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 909 of file os-semaphore.h.

913 {
914 }
const char * name(void) const
Get object name.
Definition os-decls.h:753

◆ ~semaphore_counting()

os::rtos::semaphore_counting::~semaphore_counting ( )
inline

This destructor shall destroy the semaphore object; the object becomes, in effect, uninitialised. An implementation may cause the destructor to set the object to an invalid value.

It is safe to destroy an initialised semaphore upon which no threads are currently blocked. The effect of destroying a semaphore upon which other threads are currently blocked is undefined.

POSIX compatibility
Inspired by sem_destroy() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 937 of file os-semaphore.h.

938 {
939 }

Member Function Documentation

◆ initial_value()

semaphore::count_t os::rtos::semaphore::initial_value ( void  ) const
inlineinherited
Parameters
None.
Returns
The numeric value set from attributes.
POSIX compatibility
Extension to standard, no POSIX similar functionality identified.
Note
Can be invoked from Interrupt Service Routines.

Definition at line 762 of file os-semaphore.h.

763 {
764 return initial_value_;
765 }

◆ max_value()

semaphore::count_t os::rtos::semaphore::max_value ( void  ) const
inlineinherited
Parameters
None.
Returns
The numeric value set from attributes.
POSIX compatibility
Extension to standard, no POSIX similar functionality identified.
Note
Can be invoked from Interrupt Service Routines.

Definition at line 774 of file os-semaphore.h.

775 {
776 return max_value_;
777 }

◆ name()

const char * os::rtos::internal::object_named::name ( void  ) const
inlineinherited
Parameters
None.
Returns
A null terminated string.

All objects return a non-null string; anonymous objects return "-".

Note
Can be invoked from Interrupt Service Routines.

Definition at line 753 of file os-decls.h.

754 {
755 return name_;
756 }

Referenced by os::memory::lifo::lifo(), os::memory::malloc_memory_resource::malloc_memory_resource(), os::rtos::message_queue_typed< T, Allocator >::message_queue_typed(), os::memory::block_pool::~block_pool(), os::rtos::event_flags::~event_flags(), os::memory::first_fit_top::~first_fit_top(), os::memory::lifo::~lifo(), os::memory::malloc_memory_resource::~malloc_memory_resource(), os::rtos::memory_pool::~memory_pool(), os::rtos::message_queue::~message_queue(), os::rtos::mutex::~mutex(), os::rtos::semaphore::~semaphore(), os::rtos::thread::~thread(), os::rtos::timer::~timer(), os::rtos::memory_pool::alloc(), os::rtos::thread::cancel(), os::rtos::event_flags::clear(), os::rtos::mutex::consistent(), os::rtos::thread::detach(), os::memory::new_delete_memory_resource::do_allocate(), os::memory::block_pool::do_allocate(), os::memory::first_fit_top::do_allocate(), os::memory::lifo::do_allocate(), os::memory::malloc_memory_resource::do_allocate(), os::rtos::thread::flags_raise(), os::rtos::memory_pool::free(), os::rtos::event_flags::get(), os::rtos::thread::interrupt(), os::rtos::thread::join(), os::rtos::thread::kill(), os::rtos::internal::terminated_threads_list::link(), os::rtos::mutex::lock(), os::rtos::memory::memory_resource::out_of_memory_handler(), os::rtos::semaphore::post(), os::rtos::mutex::prio_ceiling(), os::rtos::mutex::prio_ceiling(), os::rtos::thread::priority(), os::rtos::thread::priority_inherited(), os::rtos::event_flags::raise(), os::rtos::message_queue::receive(), os::rtos::memory_pool::reset(), os::rtos::message_queue::reset(), os::rtos::mutex::reset(), os::rtos::semaphore::reset(), os::rtos::thread::resume(), os::rtos::message_queue::send(), os::rtos::clock::sleep_for(), os::rtos::timer::start(), os::rtos::timer::stop(), os::rtos::memory_pool::timed_alloc(), os::rtos::mutex::timed_lock(), os::rtos::message_queue::timed_receive(), os::rtos::message_queue::timed_send(), os::rtos::semaphore::timed_wait(), os::rtos::event_flags::timed_wait(), os::rtos::memory::memory_resource::trace_print_statistics(), os::rtos::memory_pool::try_alloc(), os::rtos::mutex::try_lock(), os::rtos::message_queue::try_receive(), os::rtos::message_queue::try_send(), os::rtos::event_flags::try_wait(), os::rtos::semaphore::try_wait(), os::rtos::internal::ready_threads_list::unlink_head(), os::rtos::mutex::unlock(), os::rtos::event_flags::wait(), os::rtos::semaphore::wait(), and os::rtos::event_flags::waiting().

◆ operator delete()

void os::rtos::internal::object_named_system::operator delete ( void *  ptr,
std::size_t  bytes 
)
inlinestaticinherited
Parameters
ptrPointer to object.
bytesNumber of bytes to deallocate.
Returns
Nothing.

The deallocation function (3.7.4.2) called by a delete-expression to render the value of ptr invalid.

ptr shall be a null pointer or its value shall be a value returned by an earlier call to the (possibly replaced) operator new() which has not been invalidated by an intervening call to operator delete(void*).

If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operator new.

The storage is deallocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 120 of file os-inlines.h.

121 {
122 assert (!interrupts::in_handler_mode ());
123
124 rtos::memory::allocator<char> ().deallocate (static_cast<char*> (ptr),
125 bytes);
126 }
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1101

References os::rtos::memory::allocator_stateless_default_resource< T >::deallocate(), and os::rtos::interrupts::in_handler_mode().

◆ operator delete[]()

void os::rtos::internal::object_named_system::operator delete[] ( void *  ptr,
std::size_t  bytes 
)
inlinestaticinherited
Parameters
ptrPointer to array of objects.
bytesNumber of bytes to deallocate.
Returns
Nothing.

The deallocation function (3.7.4.2) called by the array form of a delete-expression to render the value of ptr invalid.

If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operator new.

The storage is deallocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 141 of file os-inlines.h.

142 {
143 // Forward array deallocation to single element deallocation.
144 operator delete (ptr, bytes);
145 }

◆ operator new() [1/2]

void * os::rtos::internal::object_named_system::operator new ( std::size_t  bytes)
inlinestaticinherited
Parameters
bytesNumber of bytes to allocate.
Returns
Pointer to allocated object.

The allocation function (3.7.4.1) called by a new-expression (5.3.4) to allocate a storage of size bytes suitably aligned to represent any object of that size. Return a non-null pointer to suitably aligned storage (3.7.4).

The storage is allocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 43 of file os-inlines.h.

44 {
45 assert (!interrupts::in_handler_mode ());
46
47 return rtos::memory::allocator<char> ().allocate (bytes);
48 }

References os::rtos::memory::allocator_stateless_default_resource< T >::allocate(), and os::rtos::interrupts::in_handler_mode().

◆ operator new() [2/2]

void * os::rtos::internal::object_named_system::operator new ( std::size_t  bytes,
void *  ptr 
)
inlinestaticinherited
Parameters
bytesNumber of bytes to emplace.
ptrPointer to location to emplace the object.
Returns
Pointer to emplaced object.

The allocation function (3.7.4.1) called by a placement new-expression to allocate a storage of size bytes suitably aligned to represent any object of that size. Return a non-null pointer to suitably aligned storage (3.7.4).

The storage is allocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 80 of file os-inlines.h.

81 {
82 return ptr;
83 }

◆ operator new[]() [1/2]

void * os::rtos::internal::object_named_system::operator new[] ( std::size_t  bytes)
inlinestaticinherited
Parameters
bytesNumber of bytes to allocate.
Returns
Pointer to allocated array.

The allocation function (3.7.4.1) called by the array form of a new-expression (5.3.4) to allocate a storage of size bytes suitably aligned to represent any array object of that size or smaller.

The storage is allocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 61 of file os-inlines.h.

62 {
63 // Forward array allocation to single element allocation.
64 return operator new (bytes);
65 }

◆ operator new[]() [2/2]

void * os::rtos::internal::object_named_system::operator new[] ( std::size_t  bytes,
void *  ptr 
)
inlinestaticinherited
Parameters
bytesNumber of bytes to emplace.
ptrPointer to location to emplace the object.
Returns
Pointer to emplaced array.

The allocation function (3.7.4.1) called by the array form of a placement new-expression to allocate a storage of size bytes suitably aligned to represent any array object of that size or smaller.

The storage is allocated using the RTOS system allocator.

Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 97 of file os-inlines.h.

98 {
99 // Forward array allocation to single element allocation.
100 return operator new (bytes, ptr);
101 }

◆ operator==() [1/2]

bool os::rtos::semaphore::operator== ( const semaphore rhs) const
inlineinherited
Return values
trueThe given semaphore is the same as this semaphore.
falseThe semaphores are different.

Identical semaphores should have the same memory address.

Definition at line 750 of file os-semaphore.h.

751 {
752 return this == &rhs;
753 }

◆ operator==() [2/2]

bool os::rtos::semaphore_counting::operator== ( const semaphore_counting rhs) const
Return values
trueThe given semaphore is the same as this semaphore.
falseThe semaphores are different.

◆ post()

result_t os::rtos::semaphore::post ( void  )
inherited
Parameters
None.
Return values
result::okThe semaphore was posted.
EAGAINThe maximum count value was exceeded.
ENOTRECOVERABLEThe semaphore could not be posted (extension to POSIX).

Perform a post operation on the semaphore, informing the waiting consumers that one more resource is available. The semaphore count is incremented, up to max_value.

If the semaphore count resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become unlocked.

If the count of the semaphore resulting from this operation is zero, then one of the threads blocked waiting for the semaphore shall be allowed to return successfully from its call to wait().

If the Process Scheduling option is supported, the thread to be unblocked shall be chosen in a manner appropriate to the scheduling policies and parameters in effect for the blocked threads. In the case of the schedulers SCHED_FIFO and SCHED_RR, the highest priority waiting thread shall be unblocked, and if there is more than one highest priority thread blocked waiting for the semaphore, then the highest priority thread that has been waiting the longest shall be unblocked. If the Process Scheduling option is not defined, the choice of a thread to unblock is unspecified. If the scheduling policy is SCHED_SPORADIC, the semantics are as per SCHED_FIFO.

POSIX compatibility
Inspired by sem_post() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Note
Can be invoked from Interrupt Service Routines.
Warning
Applications using these functions may be subject to priority inversion.

Definition at line 339 of file os-semaphore.cpp.

340 {
341
342#if defined(OS_USE_RTOS_PORT_SEMAPHORE)
343
344#if defined(OS_TRACE_RTOS_SEMAPHORE)
345 trace::printf ("%s() @%p %s\n", __func__, this, name ());
346#endif
347
348 return port::semaphore::post (this);
349
350#else
351
352 // Don't call this from high priority interrupts.
353 assert (port::interrupts::is_priority_valid ());
354
355 {
356 // ----- Enter critical section ---------------------------------------
357 interrupts::critical_section ics;
358
359 if (count_ >= this->max_value_)
360 {
361#if defined(OS_TRACE_RTOS_SEMAPHORE)
362 trace::printf ("%s() @%p %s EAGAIN\n", __func__, this, name ());
363#endif
364 return EAGAIN;
365 }
366
367#pragma GCC diagnostic push
368#if defined(__clang__)
369#pragma clang diagnostic ignored "-Wdeprecated-volatile"
370#elif defined(__GNUC__)
371#pragma GCC diagnostic ignored "-Wvolatile"
372#endif
373 ++count_;
374#pragma GCC diagnostic pop
375
376#if defined(OS_TRACE_RTOS_SEMAPHORE)
377 trace::printf ("%s() @%p %s count %u\n", __func__, this, name (),
378 count_);
379#endif
380 // ----- Exit critical section ----------------------------------------
381 }
382
383 // Wake-up one thread.
384 list_.resume_one ();
385
386 return result::ok;
387
388#endif
389 }
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:179

References os::rtos::internal::object_named::name(), os::rtos::result::ok, and os::trace::printf().

◆ reset()

result_t os::rtos::semaphore::reset ( void  )
inherited
Parameters
None.
Return values
result::okThe semaphore was reset.
EPERMCannot be invoked from an Interrupt Service Routines.

Reset the counter to the initial value.

POSIX compatibility
Extension to standard, no POSIX similar functionality identified.
Warning
Cannot be invoked from Interrupt Service Routines.

Definition at line 759 of file os-semaphore.cpp.

760 {
761#if defined(OS_TRACE_RTOS_SEMAPHORE)
762 trace::printf ("%s() @%p %s <%u\n", __func__, this, name (), count_);
763#endif
764
765 // Don't call this from interrupt handlers.
767
768#if defined(OS_USE_RTOS_PORT_SEMAPHORE)
769
770 return port::semaphore::reset (this);
771
772#else
773
774 {
775 // ----- Enter critical section ---------------------------------------
776 interrupts::critical_section ics;
777
778 internal_init_ ();
779 return result::ok;
780 // ----- Exit critical section ----------------------------------------
781 }
782
783#endif
784 }
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1101

References os::rtos::interrupts::in_handler_mode(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, and os::trace::printf().

◆ timed_wait()

result_t os::rtos::semaphore::timed_wait ( clock::duration_t  timeout)
inherited
Parameters
[in]timeoutTimeout to wait.
Return values
result::okThe calling process successfully performed the semaphore lock operation.
EPERMCannot be invoked from an Interrupt Service Routines.
EINVALInvalid timeout (POSIX limits the timeout to 1000 million ns)
ETIMEDOUTThe semaphore could not be locked before the specified timeout expired.
ENOTRECOVERABLESemaphore wait failed (extension to POSIX).
EDEADLKA deadlock condition was detected.
EINTRThe operation was interrupted.

Try to perform a lock operation; if the semaphore cannot be locked without waiting for another process or thread to unlock the semaphore by performing a post() function, this wait shall be terminated when the specified timeout expires.

The timeout shall expire after the number of time units (that is when the value of that clock equals or exceeds (now()+duration). The resolution of the timeout shall be the resolution of the clock on which it is based.

Under no circumstance shall the function fail with a timeout if the semaphore can be locked immediately. The validity of the timeout need not be checked if the semaphore can be locked immediately.

The clock used for timeouts can be specified via the clock attribute. By default, the clock derived from the scheduler timer is used, and the durations are expressed in ticks.

POSIX compatibility
Inspired by sem_timedwait() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Differences from the standard:
  • the timeout is not expressed as an absolute time point, but as a relative number of timer ticks (by default, the SysTick clock for CMSIS).
  • for consistency reasons, EWOULDBLOCK is used, instead of EAGAIN
Warning
Cannot be invoked from Interrupt Service Routines.
Applications using these functions may be subject to priority inversion.

Definition at line 598 of file os-semaphore.cpp.

599 {
600#if defined(OS_TRACE_RTOS_SEMAPHORE)
601#pragma GCC diagnostic push
602#if defined(__clang__)
603#elif defined(__GNUC__)
604#pragma GCC diagnostic ignored "-Wuseless-cast"
605#endif
606 trace::printf ("%s(%u) @%p %s <%u\n", __func__,
607 static_cast<unsigned int> (timeout), this, name (),
608 count_);
609#pragma GCC diagnostic pop
610#endif
611
612 // Don't call this from interrupt handlers.
614 // Don't call this from critical regions.
615 os_assert_err (!scheduler::locked (), EPERM);
616
617#if defined(OS_USE_RTOS_PORT_SEMAPHORE)
618
619 return port::semaphore::timed_wait (this, timeout);
620
621#else
622
623 // Extra test before entering the loop, with its inherent weight.
624 // Trade size for speed.
625 {
626 // ----- Enter critical section ---------------------------------------
627 interrupts::critical_section ics;
628
629 if (internal_try_wait_ ())
630 {
631 return result::ok;
632 }
633 // ----- Exit critical section ----------------------------------------
634 }
635
636 thread& crt_thread = this_thread::thread ();
637
638 // Prepare a list node pointing to the current thread.
639 // Do not worry for being on stack, it is temporarily linked to the
640 // list and guaranteed to be removed before this function returns.
641 internal::waiting_thread_node node{ crt_thread };
642
643 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
644 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
645
646 // Prepare a timeout node pointing to the current thread.
647 internal::timeout_thread_node timeout_node{ timeout_timestamp,
648 crt_thread };
649
650 for (;;)
651 {
652 {
653 // ----- Enter critical section -----------------------------------
654 interrupts::critical_section ics;
655
656 if (internal_try_wait_ ())
657 {
658 return result::ok;
659 }
660
661 // Add this thread to the semaphore waiting list,
662 // and the clock timeout list.
663 scheduler::internal_link_node (list_, node, clock_list,
664 timeout_node);
665 // state::suspended set in above link().
666 // ----- Exit critical section ------------------------------------
667 }
668
670
671 // Remove the thread from the semaphore waiting list,
672 // if not already removed by post() and from the clock
673 // timeout list, if not already removed by the timer.
674 scheduler::internal_unlink_node (node, timeout_node);
675
676 if (crt_thread.interrupted ())
677 {
678#if defined(OS_TRACE_RTOS_SEMAPHORE)
679#pragma GCC diagnostic push
680#if defined(__clang__)
681#elif defined(__GNUC__)
682#pragma GCC diagnostic ignored "-Wuseless-cast"
683#endif
684 trace::printf ("%s(%u) EINTR @%p %s\n", __func__,
685 static_cast<unsigned int> (timeout), this,
686 name ());
687#pragma GCC diagnostic pop
688#endif
689 return EINTR;
690 }
691
692 if (clock_->steady_now () >= timeout_timestamp)
693 {
694#if defined(OS_TRACE_RTOS_SEMAPHORE)
695#pragma GCC diagnostic push
696#if defined(__clang__)
697#elif defined(__GNUC__)
698#pragma GCC diagnostic ignored "-Wuseless-cast"
699#endif
700 trace::printf ("%s(%u) ETIMEDOUT @%p %s\n", __func__,
701 static_cast<unsigned int> (timeout), this,
702 name ());
703#pragma GCC diagnostic pop
704#endif
705 return ETIMEDOUT;
706 }
707 }
708
709 /* NOTREACHED */
710 return ENOTRECOVERABLE;
711
712#endif
713 }
Standard thread.
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:88
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:858
thread & thread(void)
Get the current running thread.

References os::rtos::interrupts::in_handler_mode(), os::rtos::thread::interrupted(), os::rtos::scheduler::locked(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, os::trace::printf(), os::rtos::port::scheduler::reschedule(), and os::rtos::this_thread::thread().

◆ try_wait()

result_t os::rtos::semaphore::try_wait ( void  )
inherited
Parameters
None.
Return values
result::okThe calling process successfully performed the semaphore lock operation.
EPERMCannot be invoked from an Interrupt Service Routines.
EWOULDBLOCKThe semaphore was already locked.
ENOTRECOVERABLESemaphore wait failed (extension to POSIX).
EDEADLKA deadlock condition was detected.
EINTRThe operation was interrupted.

Tries to perform a lock operation only if the semaphore is currently not locked; that is, if the semaphore value is currently positive it decrements it and returns success. Otherwise, it shall not lock the semaphore.

Upon successful return, the state of the semaphore shall be locked and shall remain locked until the post() function is executed and returns successfully.

POSIX compatibility
Inspired by sem_trywait() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Note
Can be invoked from Interrupt Service Routines.
Warning
Applications using these functions may be subject to priority inversion.

Definition at line 524 of file os-semaphore.cpp.

525 {
526#if defined(OS_TRACE_RTOS_SEMAPHORE)
527 trace::printf ("%s() @%p %s <%u\n", __func__, this, name (), count_);
528#endif
529
530 // Don't call this from high priority interrupts.
531 assert (port::interrupts::is_priority_valid ());
532
533#if defined(OS_USE_RTOS_PORT_SEMAPHORE)
534
535 return port::semaphore::try_wait (this);
536
537#else
538
539 {
540 // ----- Enter critical section ---------------------------------------
541 interrupts::critical_section ics;
542
543 if (internal_try_wait_ ())
544 {
545 return result::ok;
546 }
547 else
548 {
549 return EWOULDBLOCK;
550 }
551 // ----- Exit critical section ----------------------------------------
552 }
553
554#endif
555 }

References os::rtos::internal::object_named::name(), os::rtos::result::ok, and os::trace::printf().

◆ value()

semaphore::count_t os::rtos::semaphore::value ( void  ) const
inherited
Parameters
None.
Returns
The semaphore count value.

The value() function shall return the value of the semaphore without affecting the state of the semaphore. The value represents an actual semaphore value that occurred at some unspecified time during the call, but it need not be the actual value of the semaphore when it is returned to the calling process. This value reflects the number of available resources.

If the semaphore is locked, then the returned value shall either be set to zero or to a negative number whose absolute value represents the number of processes waiting for the semaphore at some unspecified time during the call.

POSIX compatibility
Inspired by sem_getvalue() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Note
Can be invoked from Interrupt Service Routines.

Definition at line 740 of file os-semaphore.cpp.

741 {
742#if !defined(OS_USE_RTOS_PORT_SEMAPHORE)
743 return (count_ > 0) ? count_ : 0;
744#else
745 return count_;
746#endif
747 }

◆ wait()

result_t os::rtos::semaphore::wait ( void  )
inherited
Parameters
None.
Return values
result::okThe calling process successfully performed the semaphore lock operation.
EPERMCannot be invoked from an Interrupt Service Routines.
ENOTRECOVERABLESemaphore wait failed (extension to POSIX).
EDEADLKA deadlock condition was detected.
EINTRThe operation was interrupted.

Perform a lock operation on the semaphore.

If the current value is positive, it is decremented, and the call returns immediately

If the semaphore value is currently zero, then the calling thread shall not return from the call to wait() until it either locks the semaphore or the call is interrupted by a signal.

Upon successful return, the state of the semaphore shall be locked and shall remain locked until the post() function is executed and returns successfully.

The function is interruptible by the delivery of an external event (signal, thread cancel, etc).

POSIX compatibility
Inspired by sem_wait() from <semaphore.h> (IEEE Std 1003.1, 2013 Edition).
Warning
Cannot be invoked from Interrupt Service Routines.
Applications using these functions may be subject to priority inversion.

Definition at line 424 of file os-semaphore.cpp.

425 {
426#if defined(OS_TRACE_RTOS_SEMAPHORE)
427 trace::printf ("%s() @%p %s <%u\n", __func__, this, name (), count_);
428#endif
429
430 // Don't call this from interrupt handlers.
432 // Don't call this from critical regions.
433 os_assert_err (!scheduler::locked (), EPERM);
434
435#if defined(OS_USE_RTOS_PORT_SEMAPHORE)
436
437 return port::semaphore::wait (this);
438
439#else
440
441 // Extra test before entering the loop, with its inherent weight.
442 // Trade size for speed.
443 {
444 // ----- Enter critical section ---------------------------------------
445 interrupts::critical_section ics;
446
447 if (internal_try_wait_ ())
448 {
449 return result::ok;
450 }
451 // ----- Exit critical section ----------------------------------------
452 }
453
454 thread& crt_thread = this_thread::thread ();
455
456 // Prepare a list node pointing to the current thread.
457 // Do not worry for being on stack, it is temporarily linked to the
458 // list and guaranteed to be removed before this function returns.
459 internal::waiting_thread_node node{ crt_thread };
460
461 for (;;)
462 {
463 {
464 // ----- Enter critical section -----------------------------------
465 interrupts::critical_section ics;
466
467 if (internal_try_wait_ ())
468 {
469 return result::ok;
470 }
471
472 // Add this thread to the semaphore waiting list.
473 scheduler::internal_link_node (list_, node);
474 // state::suspended set in above link().
475 // ----- Exit critical section ------------------------------------
476 }
477
479
480 // Remove the thread from the semaphore waiting list,
481 // if not already removed by post().
482 scheduler::internal_unlink_node (node);
483
484 if (crt_thread.interrupted ())
485 {
486#if defined(OS_TRACE_RTOS_SEMAPHORE)
487 trace::printf ("%s() EINTR @%p %s\n", __func__, this, name ());
488#endif
489 return EINTR;
490 }
491 }
492
493 /* NOTREACHED */
494 return ENOTRECOVERABLE;
495
496#endif
497 }

References os::rtos::interrupts::in_handler_mode(), os::rtos::thread::interrupted(), os::rtos::scheduler::locked(), os::rtos::internal::object_named::name(), os::rtos::result::ok, os_assert_err, os::trace::printf(), os::rtos::port::scheduler::reschedule(), and os::rtos::this_thread::thread().


The documentation for this class was generated from the following file: