Name
cyg_thread_yield, cyg_thread_delay, cyg_thread_suspend, cyg_thread_resume, cyg_thread_release, cyg_thread_set_affinity, cyg_thread_get_affinity — Control whether or not a thread is running
Synopsis
#include <cyg/kernel/kapi.h>
void cyg_thread_yield
( | void) ; |
void cyg_thread_delay
( | cyg_tick_count_t delay
) ; |
void cyg_thread_suspend
( | cyg_handle_t thread
) ; |
void cyg_thread_resume
( | cyg_handle_t thread
) ; |
void cyg_thread_release
( | cyg_handle_t thread
) ; |
void cyg_thread_set_affinity
( | cyg_handle_t thread , |
HAL_SMP_CPU_MASK mask
) ; |
void cyg_thread_get_affinity
( | cyg_handle_t thread , |
HAL_SMP_CPU_MASK *mask
) ; |
Description
These functions provide some control over whether or not a particular
thread can run. Apart from the required use of
cyg_thread_resume
to start a newly-created
thread, application code should normally use proper synchronization
primitives such as condition variables or mail boxes.
Yield
cyg_thread_yield
allows a thread to relinquish
control of the processor to some other runnable thread which has the
same priority. This can have no effect on any higher-priority thread
since, if such a thread were runnable, the current thread would have
been preempted in its favour. Similarly it can have no effect on any
lower-priority thread because the current thread will always be run in
preference to those. As a consequence this function is only useful
in configurations with a scheduler that allows multiple threads to run
at the same priority, for example the mlqueue scheduler. If instead
the bitmap scheduler was being used then
cyg_thread_yield()
would serve no purpose.
Even if a suitable scheduler such as the mlqueue scheduler has been
configured, cyg_thread_yield
will still rarely
prove useful: instead timeslicing will be used to ensure that all
threads of a given priority get a fair slice of the available
processor time. However it is possible to disable timeslicing via the
configuration option CYGSEM_KERNEL_SCHED_TIMESLICE
,
in which case cyg_thread_yield
can be used to
implement a form of cooperative multitasking.
Delay
cyg_thread_delay
allows a thread to suspend until
the specified number of clock ticks have occurred. For example, if a
value of 1 is used and the system clock runs at a frequency of 100Hz
then the thread will sleep for up to 10 milliseconds. This
functionality depends on the presence of a real-time system clock, as
controlled by the configuration option
CYGVAR_KERNEL_COUNTERS_CLOCK
.
If the application requires delays measured in milliseconds or similar
units rather than in clock ticks, some calculations are needed to
convert between these units as described in Clocks. Usually these calculations can be done by
the application developer, or at compile-time. Performing such
calculations prior to every call to
cyg_thread_delay
adds unnecessary overhead to the
system.
Suspend and Resume
Associated with each thread is a suspend counter. When a thread is
first created this counter is initialized to 1.
cyg_thread_suspend
can be used to increment the
suspend counter, and cyg_thread_resume
decrements
it. The scheduler will never run a thread with a non-zero suspend
counter. Therefore a newly created thread will not run until it has
been resumed.
An occasional problem with the use of suspend and resume functionality
is that a thread gets suspended more times than it is resumed and
hence never becomes runnable again. This can lead to very confusing
behaviour. To help with debugging such problems the kernel provides a
configuration option
CYGNUM_KERNEL_MAX_SUSPEND_COUNT_ASSERT
which
imposes an upper bound on the number of suspend calls without matching
resumes, with a reasonable default value. This functionality depends
on infrastructure assertions being enabled.
Releasing a Blocked Thread
When a thread is blocked on a synchronization primitive such as a
semaphore or a mutex, or when it is waiting for an alarm to trigger,
it can be forcibly woken up using
cyg_thread_release
. Typically this will call the
affected synchronization primitive to return false, indicating that
the operation was not completed successfully. This function has to be
used with great care, and in particular it should only be used on
threads that have been designed appropriately and check all return
codes. If instead it were to be used on, say, an arbitrary thread that
is attempting to claim a mutex then that thread might not bother to
check the result of the mutex lock operation - usually there would be
no reason to do so. Therefore the thread will now continue running in
the false belief that it has successfully claimed a mutex lock, and
the resulting behaviour is undefined. If the system has been built
with assertions enabled then it is possible that an assertion will
trigger when the thread tries to release the mutex it does not
actually own.
The main use of cyg_thread_release
is in the
POSIX compatibility layer, where it is used in the implementation of
per-thread signals and cancellation handlers.
Thread Affinity
In SMP configurations, using the MLQSMP scheduler, it is possible to
control the set of CPUs on which a thread can be run. This can be
controlled by using cyg_thread_set_affinity
. In
addition to the thread handle, this function takes a bitmask that has
bit n set if that thread can run on CPU
n and clear if it cannot. Bits corresponding to
CPUs that are not present are ignored. A mask of all ones allows the
thread to run on any CPU and is the default setting. A value of all
zeroes will prevent the thread running at all. The function
cyg_thread_get_affinity
returns the current
setting of the thread's affinity mask.
These functions are also present in non-SMP configurations to retain
compatibility. In this case
cyg_thread_set_affinity
is a no-op, and
cyg_thread_get_affinity
returns a mask with just
the bit for CPU 0 set.
Valid contexts
cyg_thread_yield
can only be called from thread
context, A DSR must always run to completion and cannot yield the
processor to some thread. cyg_thread_suspend
,
cyg_thread_resume
, and
cyg_thread_release
may be called from thread or
DSR context.
2024-03-18 | Open Publication License |