mirror of
https://github.com/azure-rtos/threadx
synced 2025-01-16 07:42:57 +08:00
Initial commit
This commit is contained in:
commit
852421fda0
40
.gitattributes
vendored
Executable file
40
.gitattributes
vendored
Executable file
@ -0,0 +1,40 @@
|
||||
.git* export-ignore
|
||||
.hooks* export-ignore
|
||||
|
||||
# Custom attribute to mark sources as using our C code style.
|
||||
[attr]our-c-style whitespace=tab-in-indent eol=lf format.clang-format-6.0
|
||||
|
||||
# Custom attribute to mark sources as generated.
|
||||
# Do not perform whitespace checks. Do not format.
|
||||
[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-6.0
|
||||
|
||||
bootstrap eol=lf
|
||||
configure eol=lf
|
||||
*.[1-9] eol=lf
|
||||
*.bash eol=lf
|
||||
*.sh eol=lf
|
||||
*.sh.in eol=lf
|
||||
|
||||
*.bat eol=crlf
|
||||
*.bat.in eol=crlf
|
||||
*.sln eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
|
||||
*.pfx -text
|
||||
*.png -text
|
||||
*.png.in -text
|
||||
|
||||
*.c our-c-style
|
||||
*.cc our-c-style
|
||||
*.cpp our-c-style
|
||||
*.cu our-c-style
|
||||
*.cxx our-c-style
|
||||
*.h our-c-style
|
||||
*.hh our-c-style
|
||||
*.hpp our-c-style
|
||||
*.hxx our-c-style
|
||||
*.notcu our-c-style
|
||||
|
||||
*.cmake whitespace=tab-in-indent
|
||||
*.rst whitespace=tab-in-indent conflict-marker-size=79
|
||||
*.txt whitespace=tab-in-indent
|
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
.vscode/
|
||||
_deps/
|
||||
build/
|
||||
CMakeFiles/
|
||||
CMakeScripts/
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
|
44
CMakeLists.txt
Normal file
44
CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
||||
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
|
||||
|
||||
# Set up the project
|
||||
project(threadx
|
||||
VERSION 6.0.0
|
||||
LANGUAGES C ASM
|
||||
)
|
||||
|
||||
if(NOT DEFINED THREADX_ARCH)
|
||||
message(FATAL_ERROR "Error: THREADX_ARCH not defined")
|
||||
endif()
|
||||
if(NOT DEFINED THREADX_TOOLCHAIN)
|
||||
message(FATAL_ERROR "Error: THREADX_TOOLCHAIN not defined")
|
||||
endif()
|
||||
|
||||
# Define our target library and an alias for consumers
|
||||
add_library(${PROJECT_NAME})
|
||||
add_library("azrtos::${PROJECT_NAME}" ALIAS ${PROJECT_NAME})
|
||||
|
||||
# A place for generated/copied include files (no need to change)
|
||||
set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc)
|
||||
|
||||
# Pick up the port specific variables and apply them
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN})
|
||||
|
||||
# Pick up the common stuff
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common)
|
||||
|
||||
|
||||
|
||||
|
||||
# If the user provided an override, copy it to the custom directory
|
||||
if (NOT TX_USER_FILE)
|
||||
message(STATUS "Using default tx_user.h file")
|
||||
set(TX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/common/inc/tx_user_sample.h)
|
||||
else()
|
||||
message(STATUS "Using custom tx_user.h file from ${UX_USER_FILE}")
|
||||
endif()
|
||||
configure_file(${TX_USER_FILE} ${CUSTOM_INC_DIR}/tx_user.h COPYONLY)
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CUSTOM_INC_DIR}
|
||||
)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_INCLUDE_USER_DEFINE_FILE" )
|
246
LICENSE.txt
Normal file
246
LICENSE.txt
Normal file
@ -0,0 +1,246 @@
|
||||
MICROSOFT SOFTWARE LICENSE TERMS
|
||||
|
||||
MICROSOFT AZURE RTOS
|
||||
|
||||
Shape
|
||||
|
||||
These license terms are an agreement between you and Microsoft Corporation (or
|
||||
one of its affiliates). They apply to the software named above and any Microsoft
|
||||
services or software updates (except to the extent such services or updates are
|
||||
accompanied by new or additional terms, in which case those different terms
|
||||
apply prospectively and do not alter your or Microsoft’s rights relating to
|
||||
pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU
|
||||
HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.
|
||||
|
||||
INSTALLATION AND USE RIGHTS.
|
||||
|
||||
General. You may install and use the software and the included Microsoft
|
||||
applications solely for internal development, testing and evaluation purposes.
|
||||
Any distribution or production use requires a separate license as set forth in
|
||||
Section 2.
|
||||
|
||||
Contributions. Microsoft welcomes contributions to this software. In the event
|
||||
that you make a contribution to this software you will be required to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and
|
||||
actually do, grant Microsoft the rights to use your contribution. For details,
|
||||
visit https://cla.microsoft.com.
|
||||
|
||||
Included Microsoft Applications. The software includes other Microsoft
|
||||
applications which are governed by the licenses embedded in or made available
|
||||
with those applications.
|
||||
|
||||
Third Party Components. The software may include third party components with
|
||||
separate legal notices or governed by other agreements, as may be described
|
||||
within the software or in the ThirdPartyNotices file(s) accompanying the
|
||||
software.
|
||||
|
||||
Competitive Benchmarking. If you are a direct competitor, and you access or use
|
||||
the software for purposes of competitive benchmarking, analysis, or intelligence
|
||||
gathering, you waive as against Microsoft, its subsidiaries, and its affiliated
|
||||
companies (including prospectively) any competitive use, access, and
|
||||
benchmarking test restrictions in the terms governing your software to the
|
||||
extent your terms of use are, or purport to be, more restrictive than
|
||||
Microsoft’s terms. If you do not waive any such purported restrictions in the
|
||||
terms governing your software, you are not allowed to access or use this
|
||||
software, and will not do so.
|
||||
|
||||
DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on
|
||||
microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file
|
||||
named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with
|
||||
the software you have the following rights in and to the software solely when
|
||||
used in combination with the hardware. In the event hardware is not listed in
|
||||
the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2.
|
||||
|
||||
Distribution and Production Use Rights.
|
||||
|
||||
You may use the software in production (e.g. program the modified or unmodified
|
||||
software to devices you own or control) and distribute (i.e. make available to
|
||||
third parties) the modified or unmodified binary image produced from this code.
|
||||
|
||||
|
||||
You may permit your device distributors or developers to copy and distribute the
|
||||
binary image as programmed or to be programmed to your devices.
|
||||
|
||||
You may redistribute the unmodified or modified source to your device
|
||||
distributors or developers. Modifications must be clearly marked. Any
|
||||
redistribution in source code form must contain this license and any other
|
||||
licenses that accompany the software.
|
||||
|
||||
Requirements. For any code you distribute, you must:
|
||||
|
||||
when distributed in binary form, except as embedded in a device, include with
|
||||
such distribution the terms of this agreement;
|
||||
|
||||
when distributed in source code form to distributors or developers of your
|
||||
devices, include with such distribution the terms of this agreement; and
|
||||
|
||||
indemnify, defend and hold harmless Microsoft from any claims, including
|
||||
attorneys’ fees, related to the distribution or use of your devices, except to
|
||||
the extent that any claim is based solely on the unmodified software.
|
||||
|
||||
Restrictions. You may not:
|
||||
|
||||
use or modify the software to create a competing real time operating system
|
||||
software;
|
||||
|
||||
remove any copyright notices or licenses contained in the software;
|
||||
|
||||
use Microsoft’s trademarks or trade dress in your application in any way that
|
||||
suggests your device or application comes from or is endorsed by Microsoft;
|
||||
|
||||
transfer individual components, specific libraries, classes, functions or code
|
||||
fragments of the software separately for purposes unrelated to the software; or
|
||||
|
||||
use or distribute the software in any way that would subject the software or
|
||||
Microsoft’s intellectual property or technology to any other license terms.
|
||||
|
||||
SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all
|
||||
other rights. Unless applicable law gives you more rights despite this
|
||||
limitation, you will not (and have no right to):
|
||||
|
||||
remove, minimize, block, or modify any notices of Microsoft or its suppliers in
|
||||
the software;
|
||||
|
||||
use the software in any way that is against the law or to create or propagate
|
||||
malware; or
|
||||
|
||||
share, publish, distribute, or lease the software (except as permitted in
|
||||
Section 2 above), or provide the software as a stand-alone offering for others
|
||||
to use.
|
||||
|
||||
DATA. This software may interact with other Microsoft products that collect data
|
||||
that is transmitted to Microsoft. To learn more about how Microsoft processes
|
||||
personal data we collect, please see the Microsoft Privacy Statement at
|
||||
https://go.microsoft.com/fwlink/?LinkId=248681.
|
||||
|
||||
EXPORT RESTRICTIONS. You must comply with all domestic and international export
|
||||
laws and regulations that apply to the software, which include restrictions on
|
||||
destinations, end users, and end use. For further information on export
|
||||
restrictions, visit https://aka.ms/exporting.
|
||||
|
||||
SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any
|
||||
support services for the software. Any support provided is “as is”, “with all
|
||||
faults”, and without warranty of any kind.
|
||||
|
||||
UPDATES. Microsoft may periodically update the software. You may obtain updates
|
||||
only from Microsoft or Microsoft-authorized sources. Updates may not include or
|
||||
support all existing software features, services, or peripheral devices.
|
||||
|
||||
TERMINATION. Without prejudice to any other rights, Microsoft may terminate this
|
||||
agreement if you fail to comply with any of its terms or conditions. In such
|
||||
event, you must destroy all copies of the software and all of its component
|
||||
parts.
|
||||
|
||||
ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for
|
||||
supplements, updates, or third-party applications, is the entire agreement for
|
||||
the software. To the extent you have entered into a separate agreement with
|
||||
Microsoft relating specifically to the software, the terms in such agreement
|
||||
shall control.
|
||||
|
||||
APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in
|
||||
the United States or Canada, the laws of the state or province where you live
|
||||
(or, if a business, where your principal place of business is located) govern
|
||||
the interpretation of this agreement, claims for its breach, and all other
|
||||
claims (including consumer protection, unfair competition, and tort claims),
|
||||
regardless of conflict of laws principles. If you acquired the software in any
|
||||
other country, its laws apply. If U.S. federal jurisdiction exists, you and
|
||||
Microsoft consent to exclusive jurisdiction and venue in the federal court in
|
||||
King County, Washington for all disputes heard in court. If not, you and
|
||||
Microsoft consent to exclusive jurisdiction and venue in the Superior Court of
|
||||
King County, Washington for all disputes heard in court.
|
||||
|
||||
CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal
|
||||
rights. You may have other rights, including consumer rights, under the laws of
|
||||
your state or country. Separate and apart from your relationship with Microsoft,
|
||||
you may also have rights with respect to the party from which you acquired the
|
||||
software. This agreement does not change those other rights if the laws of your
|
||||
state or country do not permit it to do so. For example, if you acquired the
|
||||
software in one of the below regions, or mandatory country law applies, then the
|
||||
following provisions apply to you:
|
||||
|
||||
Australia. You have statutory guarantees under the Australian Consumer Law and
|
||||
nothing in this agreement is intended to affect those rights.
|
||||
|
||||
Germany and Austria.
|
||||
|
||||
i.Warranty. The properly licensed software will perform substantially as
|
||||
described in any Microsoft materials that accompany the software. However,
|
||||
Microsoft gives no contractual guarantee in relation to the licensed software.
|
||||
|
||||
ii.Limitation of Liability. In case of intentional conduct, gross negligence,
|
||||
claims based on the Product Liability Act, as well as, in case of death or
|
||||
personal or physical injury, Microsoft is liable according to the statutory law.
|
||||
|
||||
|
||||
Subject to the foregoing clause ii., Microsoft will only be liable for slight
|
||||
negligence if Microsoft is in breach of such material contractual obligations,
|
||||
the fulfillment of which facilitate the due performance of this agreement, the
|
||||
breach of which would endanger the purpose of this agreement and the compliance
|
||||
with which a party may constantly trust in (so-called "cardinal obligations").
|
||||
In other cases of slight negligence, Microsoft will not be liable for slight
|
||||
negligence.
|
||||
|
||||
DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF
|
||||
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO
|
||||
THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED
|
||||
WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
|
||||
NON-INFRINGEMENT.
|
||||
|
||||
LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING
|
||||
DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM
|
||||
MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT
|
||||
RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL,
|
||||
INDIRECT, OR INCIDENTAL DAMAGES.
|
||||
|
||||
This limitation applies to (a) anything related to the software, services,
|
||||
content (including code) on third party Internet sites, or third party
|
||||
applications; and (b) claims for breach of contract, warranty, guarantee, or
|
||||
condition; strict liability, negligence, or other tort; or any other claim; in
|
||||
each case to the extent permitted by applicable law.
|
||||
|
||||
It also applies even if Microsoft knew or should have known about the
|
||||
possibility of the damages. The above limitation or exclusion may not apply to
|
||||
you because your state, province, or country may not allow the exclusion or
|
||||
limitation of incidental, consequential, or other damages.
|
||||
|
||||
|
||||
|
||||
Please note: As this software is distributed in Canada, some of the clauses in
|
||||
this agreement are provided below in French.
|
||||
|
||||
Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce
|
||||
contrat sont fournies ci-dessous en français.
|
||||
|
||||
EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel
|
||||
». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft
|
||||
n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits
|
||||
additionnels en vertu du droit local sur la protection des consommateurs, que ce
|
||||
contrat ne peut modifier. La ou elles sont permises par le droit locale, les
|
||||
garanties implicites de qualité marchande, d’adéquation à un usage particulier
|
||||
et d’absence de contrefaçon sont exclues.
|
||||
|
||||
LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES
|
||||
DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une
|
||||
indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous
|
||||
ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris
|
||||
les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
|
||||
|
||||
Cette limitation concerne:
|
||||
|
||||
•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le
|
||||
code) figurant sur des sites Internet tiers ou dans des programmes tiers; et
|
||||
|
||||
•les réclamations au titre de violation de contrat ou de garantie, ou au titre
|
||||
de responsabilité stricte, de négligence ou d’une autre faute dans la limite
|
||||
autorisée par la loi en vigueur.
|
||||
|
||||
Elle s’applique également, même si Microsoft connaissait ou devrait connaître
|
||||
l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la
|
||||
limitation de responsabilité pour les dommages indirects, accessoires ou de
|
||||
quelque nature que ce soit, il se peut que la limitation ou l’exclusion
|
||||
ci-dessus ne s’appliquera pas à votre égard.
|
||||
|
||||
EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous
|
||||
pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent
|
||||
contrat ne modifie pas les droits que vous confèrent les lois de votre pays si
|
||||
celles-ci ne le permettent pas.
|
16
LICENSED-HARDWARE.txt
Normal file
16
LICENSED-HARDWARE.txt
Normal file
@ -0,0 +1,16 @@
|
||||
LICENSED HARDWARE LIST
|
||||
|
||||
Last Updated: 2020-05-08
|
||||
|
||||
Microsoft has entered into OEM Agreements with manufacturers of the following
|
||||
microprocessors and microcontrollers (the “hardware”) to enable those
|
||||
manufacturers to include and distribute Azure RTOS in certain hardware. If you
|
||||
have obtained and/or are developing on microprocessor(s) and/or
|
||||
microcontroller(s) (“hardware”) listed below you inherit the “Distribution and
|
||||
Production Use” rights in Section 2 of the Microsoft Software License Terms for
|
||||
Microsoft Azure RTOS. If hardware is not listed below, you do not have those
|
||||
rights.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
More coming soon. Please check back frequently for updates.
|
208
common/CMakeLists.txt
Normal file
208
common/CMakeLists.txt
Normal file
@ -0,0 +1,208 @@
|
||||
function(target_sources_if_not_overridden filename)
|
||||
list(FIND TX_SRC_OVERRIDES ${filename} OVERRIDE_FOUND)
|
||||
if( OVERRIDE_FOUND EQUAL -1 )
|
||||
message(STATUS "** Using original ${filename} from common/src **")
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/${filename})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# These files can be overridden by setting them in the variable list named TX_SRC_OVERRIDES
|
||||
target_sources_if_not_overridden("tx_thread_delete.c")
|
||||
target_sources_if_not_overridden("tx_thread_reset.c")
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_pool_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_block_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_pool_search.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_byte_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_event_flags_set_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_high_level.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_enter.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_kernel_setup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_misra.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_priority_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_mutex_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_front_send.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_receive.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_queue_send_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_ceiling_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_cleanup.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_semaphore_put_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_entry_exit_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_identify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_preemption_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_priority_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_relinquish.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_resume.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_shell_entry.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_sleep.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_analyze.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_handler.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_error_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_suspend.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_preempt_check.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_resume.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_suspend.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_terminate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_time_slice_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_timeout.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_wait_abort.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_time_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_time_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_activate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_deactivate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_expiration_process.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_performance_system_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_activate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_system_deactivate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_thread_entry.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_buffer_full_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_disable.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_enable.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_filter.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_event_unfilter.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_initialize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_interrupt_control.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_enter_insert.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_isr_exit_insert.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_register.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_object_unregister.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_trace_user_event_insert.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_pool_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_block_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_allocate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_pool_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_byte_release.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_event_flags_set_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_mutex_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_flush.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_front_send.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_receive.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_queue_send_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_ceiling_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_prioritize.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_semaphore_put_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_entry_exit_notify.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_info_get.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_preemption_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_priority_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_relinquish.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_reset.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_resume.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_suspend.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_terminate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_time_slice_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_wait_abort.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_activate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_create.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_deactivate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_delete.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/txe_timer_info_get.c
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
# Add the Common/inc directory to the project include list
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
|
2208
common/inc/tx_api.h
Normal file
2208
common/inc/tx_api.h
Normal file
File diff suppressed because it is too large
Load Diff
146
common/inc/tx_block_pool.h
Normal file
146
common/inc/tx_block_pool.h
Normal file
@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_block_pool.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX block memory management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_BLOCK_POOL_H
|
||||
#define TX_BLOCK_POOL_H
|
||||
|
||||
|
||||
/* Define block memory control specific data definitions. */
|
||||
|
||||
#define TX_BLOCK_POOL_ID ((ULONG) 0x424C4F43)
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
|
||||
/* Yes, in-line initialization is supported, remap the block memory pool
|
||||
initialization function. */
|
||||
|
||||
#ifndef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_block_pool_initialize() \
|
||||
_tx_block_pool_created_ptr = TX_NULL; \
|
||||
_tx_block_pool_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_block_pool_initialize() \
|
||||
_tx_block_pool_created_ptr = TX_NULL; \
|
||||
_tx_block_pool_created_count = TX_EMPTY; \
|
||||
_tx_block_pool_performance_allocate_count = ((ULONG) 0); \
|
||||
_tx_block_pool_performance_release_count = ((ULONG) 0); \
|
||||
_tx_block_pool_performance_suspension_count = ((ULONG) 0); \
|
||||
_tx_block_pool_performance_timeout_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_BLOCK_POOL_INIT
|
||||
#else
|
||||
|
||||
/* No in-line initialization is supported, use standard function call. */
|
||||
VOID _tx_block_pool_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal block memory pool management function prototypes. */
|
||||
|
||||
VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
|
||||
|
||||
/* Block pool management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_BLOCK_POOL_INIT
|
||||
#define BLOCK_POOL_DECLARE
|
||||
#else
|
||||
#define BLOCK_POOL_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created block pool list. */
|
||||
|
||||
BLOCK_POOL_DECLARE TX_BLOCK_POOL * _tx_block_pool_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created block pools. */
|
||||
|
||||
BLOCK_POOL_DECLARE ULONG _tx_block_pool_created_count;
|
||||
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of block allocates. */
|
||||
|
||||
BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_allocate_count;
|
||||
|
||||
|
||||
/* Define the total number of block releases. */
|
||||
|
||||
BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_release_count;
|
||||
|
||||
|
||||
/* Define the total number of block pool suspensions. */
|
||||
|
||||
BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of block pool timeouts. */
|
||||
|
||||
BLOCK_POOL_DECLARE ULONG _tx_block_pool_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post block pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_BLOCK_POOL_DELETE_PORT_COMPLETION
|
||||
#define TX_BLOCK_POOL_DELETE_PORT_COMPLETION(p)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
177
common/inc/tx_byte_pool.h
Normal file
177
common/inc/tx_byte_pool.h
Normal file
@ -0,0 +1,177 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_byte_pool.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX byte memory management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_BYTE_POOL_H
|
||||
#define TX_BYTE_POOL_H
|
||||
|
||||
|
||||
/* Define byte memory control specific data definitions. */
|
||||
|
||||
#define TX_BYTE_POOL_ID ((ULONG) 0x42595445)
|
||||
|
||||
#ifndef TX_BYTE_BLOCK_FREE
|
||||
#define TX_BYTE_BLOCK_FREE ((ULONG) 0xFFFFEEEEUL)
|
||||
#endif
|
||||
|
||||
#ifndef TX_BYTE_BLOCK_MIN
|
||||
#define TX_BYTE_BLOCK_MIN ((ULONG) 20)
|
||||
#endif
|
||||
|
||||
#ifndef TX_BYTE_POOL_MIN
|
||||
#define TX_BYTE_POOL_MIN ((ULONG) 100)
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
|
||||
/* Yes, in-line initialization is supported, remap the byte memory pool
|
||||
initialization function. */
|
||||
|
||||
#ifndef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_byte_pool_initialize() \
|
||||
_tx_byte_pool_created_ptr = TX_NULL; \
|
||||
_tx_byte_pool_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_byte_pool_initialize() \
|
||||
_tx_byte_pool_created_ptr = TX_NULL; \
|
||||
_tx_byte_pool_created_count = TX_EMPTY; \
|
||||
_tx_byte_pool_performance_allocate_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_release_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_merge_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_split_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_search_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_suspension_count = ((ULONG) 0); \
|
||||
_tx_byte_pool_performance_timeout_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_BYTE_POOL_INIT
|
||||
#else
|
||||
|
||||
/* No in-line initialization is supported, use standard function call. */
|
||||
VOID _tx_byte_pool_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal byte memory pool management function prototypes. */
|
||||
|
||||
UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size);
|
||||
VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
|
||||
|
||||
/* Byte pool management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_BYTE_POOL_INIT
|
||||
#define BYTE_POOL_DECLARE
|
||||
#else
|
||||
#define BYTE_POOL_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created byte pool list. */
|
||||
|
||||
BYTE_POOL_DECLARE TX_BYTE_POOL * _tx_byte_pool_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created byte pools. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_created_count;
|
||||
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of allocates. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_allocate_count;
|
||||
|
||||
|
||||
/* Define the total number of releases. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_release_count;
|
||||
|
||||
|
||||
/* Define the total number of adjacent memory fragment merges. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_merge_count;
|
||||
|
||||
|
||||
/* Define the total number of memory fragment splits. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_split_count;
|
||||
|
||||
|
||||
/* Define the total number of memory fragments searched during allocation. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_search_count;
|
||||
|
||||
|
||||
/* Define the total number of byte pool suspensions. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of byte pool timeouts. */
|
||||
|
||||
BYTE_POOL_DECLARE ULONG _tx_byte_pool_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post byte pool delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_BYTE_POOL_DELETE_PORT_COMPLETION
|
||||
#define TX_BYTE_POOL_DELETE_PORT_COMPLETION(p)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
147
common/inc/tx_event_flags.h
Normal file
147
common/inc/tx_event_flags.h
Normal file
@ -0,0 +1,147 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_event_flags.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX event flags management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_EVENT_FLAGS_H
|
||||
#define TX_EVENT_FLAGS_H
|
||||
|
||||
|
||||
/* Define event flags control specific data definitions. */
|
||||
|
||||
#define TX_EVENT_FLAGS_ID ((ULONG) 0x4456444E)
|
||||
#define TX_EVENT_FLAGS_AND_MASK ((UINT) 0x2)
|
||||
#define TX_EVENT_FLAGS_CLEAR_MASK ((UINT) 0x1)
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
|
||||
/* Yes, in-line initialization is supported, remap the event flag initialization
|
||||
function. */
|
||||
|
||||
#ifndef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_event_flags_initialize() \
|
||||
_tx_event_flags_created_ptr = TX_NULL; \
|
||||
_tx_event_flags_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_event_flags_initialize() \
|
||||
_tx_event_flags_created_ptr = TX_NULL; \
|
||||
_tx_event_flags_created_count = TX_EMPTY; \
|
||||
_tx_event_flags_performance_set_count = ((ULONG) 0); \
|
||||
_tx_event_flags_performance_get_count = ((ULONG) 0); \
|
||||
_tx_event_flags_performance_suspension_count = ((ULONG) 0); \
|
||||
_tx_event_flags_performance_timeout_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_EVENT_FLAGS_INIT
|
||||
#else
|
||||
|
||||
/* No in-line initialization is supported, use standard function call. */
|
||||
VOID _tx_event_flags_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal event flags management function prototypes. */
|
||||
|
||||
VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
|
||||
|
||||
/* Event flags management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_INIT
|
||||
#define EVENT_FLAGS_DECLARE
|
||||
#else
|
||||
#define EVENT_FLAGS_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created event flags list. */
|
||||
|
||||
EVENT_FLAGS_DECLARE TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created event flag groups. */
|
||||
|
||||
EVENT_FLAGS_DECLARE ULONG _tx_event_flags_created_count;
|
||||
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of event flag sets. */
|
||||
|
||||
EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_set_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag gets. */
|
||||
|
||||
EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag suspensions. */
|
||||
|
||||
EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag timeouts. */
|
||||
|
||||
EVENT_FLAGS_DECLARE ULONG _tx_event_flags_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* Define default post event flag group delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(g)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
111
common/inc/tx_initialize.h
Normal file
111
common/inc/tx_initialize.h
Normal file
@ -0,0 +1,111 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_initialize.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX initialization component, including */
|
||||
/* data types and external references. It is assumed that tx_api.h */
|
||||
/* and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_INITIALIZE_H
|
||||
#define TX_INITIALIZE_H
|
||||
|
||||
|
||||
/* Define constants that indicate initialization is in progress. */
|
||||
|
||||
#define TX_INITIALIZE_IN_PROGRESS ((ULONG) 0xF0F0F0F0UL)
|
||||
#define TX_INITIALIZE_ALMOST_DONE ((ULONG) 0xF0F0F0F1UL)
|
||||
#define TX_INITIALIZE_IS_FINISHED ((ULONG) 0x00000000UL)
|
||||
|
||||
|
||||
/* Define internal initialization function prototypes. */
|
||||
|
||||
VOID _tx_initialize_high_level(VOID);
|
||||
VOID _tx_initialize_kernel_setup(VOID);
|
||||
VOID _tx_initialize_low_level(VOID);
|
||||
|
||||
|
||||
/* Define the macro for adding additional port-specific global data. This macro is defined
|
||||
as white space, unless defined by tx_port.h. */
|
||||
|
||||
#ifndef TX_PORT_SPECIFIC_DATA
|
||||
#define TX_PORT_SPECIFIC_DATA
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macro for adding additional port-specific pre and post initialization processing.
|
||||
These macros is defined as white space, unless defined by tx_port.h. */
|
||||
|
||||
#ifndef TX_PORT_SPECIFIC_PRE_INITIALIZATION
|
||||
#define TX_PORT_SPECIFIC_PRE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
#ifndef TX_PORT_SPECIFIC_POST_INITIALIZATION
|
||||
#define TX_PORT_SPECIFIC_POST_INITIALIZATION
|
||||
#endif
|
||||
|
||||
#ifndef TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Initialization component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_INITIALIZE_INIT
|
||||
#define INITIALIZE_DECLARE
|
||||
#else
|
||||
#define INITIALIZE_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the unused memory pointer. The value of the first available
|
||||
memory address is placed in this variable in the low-level
|
||||
initialization function. The content of this variable is passed
|
||||
to the application's system definition function. */
|
||||
|
||||
INITIALIZE_DECLARE VOID *_tx_initialize_unused_memory;
|
||||
|
||||
|
||||
#endif
|
160
common/inc/tx_mutex.h
Normal file
160
common/inc/tx_mutex.h
Normal file
@ -0,0 +1,160 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_mutex.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX mutex management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_MUTEX_H
|
||||
#define TX_MUTEX_H
|
||||
|
||||
|
||||
/* Define mutex control specific data definitions. */
|
||||
|
||||
#define TX_MUTEX_ID ((ULONG) 0x4D555445)
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
|
||||
/* Yes, in-line initialization is supported, remap the mutex initialization
|
||||
function. */
|
||||
|
||||
#ifndef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_mutex_initialize() \
|
||||
_tx_mutex_created_ptr = TX_NULL; \
|
||||
_tx_mutex_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_mutex_initialize() \
|
||||
_tx_mutex_created_ptr = TX_NULL; \
|
||||
_tx_mutex_created_count = TX_EMPTY; \
|
||||
_tx_mutex_performance_put_count = ((ULONG) 0); \
|
||||
_tx_mutex_performance_get_count = ((ULONG) 0); \
|
||||
_tx_mutex_performance_suspension_count = ((ULONG) 0); \
|
||||
_tx_mutex_performance_timeout_count = ((ULONG) 0); \
|
||||
_tx_mutex_performance_priority_inversion_count = ((ULONG) 0); \
|
||||
_tx_mutex_performance__priority_inheritance_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_MUTEX_INIT
|
||||
#else
|
||||
|
||||
/* No in-line initialization is supported, use standard function call. */
|
||||
VOID _tx_mutex_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal mutex management function prototypes. */
|
||||
|
||||
VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr);
|
||||
VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority);
|
||||
|
||||
|
||||
/* Mutex management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_MUTEX_INIT
|
||||
#define MUTEX_DECLARE
|
||||
#else
|
||||
#define MUTEX_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created mutex list. */
|
||||
|
||||
MUTEX_DECLARE TX_MUTEX * _tx_mutex_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created mutexes. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_created_count;
|
||||
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of mutex puts. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance_put_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex gets. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex suspensions. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex timeouts. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance_timeout_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inversions. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance_priority_inversion_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inheritance conditions. */
|
||||
|
||||
MUTEX_DECLARE ULONG _tx_mutex_performance__priority_inheritance_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post mutex delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_MUTEX_DELETE_PORT_COMPLETION
|
||||
#define TX_MUTEX_DELETE_PORT_COMPLETION(m)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
173
common/inc/tx_queue.h
Normal file
173
common/inc/tx_queue.h
Normal file
@ -0,0 +1,173 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_queue.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX queue management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_QUEUE_H
|
||||
#define TX_QUEUE_H
|
||||
|
||||
|
||||
/* Define queue control specific data definitions. */
|
||||
|
||||
#define TX_QUEUE_ID ((ULONG) 0x51554555)
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
|
||||
/* Yes, in-line initialization is supported, remap the queue initialization
|
||||
function. */
|
||||
|
||||
#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_queue_initialize() \
|
||||
_tx_queue_created_ptr = TX_NULL; \
|
||||
_tx_queue_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_queue_initialize() \
|
||||
_tx_queue_created_ptr = TX_NULL; \
|
||||
_tx_queue_created_count = TX_EMPTY; \
|
||||
_tx_queue_performance_messages_sent_count = ((ULONG) 0); \
|
||||
_tx_queue_performance__messages_received_count = ((ULONG) 0); \
|
||||
_tx_queue_performance_empty_suspension_count = ((ULONG) 0); \
|
||||
_tx_queue_performance_full_suspension_count = ((ULONG) 0); \
|
||||
_tx_queue_performance_timeout_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_QUEUE_INIT
|
||||
#else
|
||||
|
||||
/* No in-line initialization is supported, use standard function call. */
|
||||
VOID _tx_queue_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the message copy macro. Note that the source and destination
|
||||
pointers must be modified since they are used subsequently. */
|
||||
|
||||
#ifndef TX_QUEUE_MESSAGE_COPY
|
||||
#define TX_QUEUE_MESSAGE_COPY(s, d, z) \
|
||||
*(d)++ = *(s)++; \
|
||||
if ((z) > ((UINT) 1)) \
|
||||
{ \
|
||||
while (--(z)) \
|
||||
{ \
|
||||
*(d)++ = *(s)++; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal queue management function prototypes. */
|
||||
|
||||
VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
|
||||
|
||||
/* Queue management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_QUEUE_INIT
|
||||
#define QUEUE_DECLARE
|
||||
#else
|
||||
#define QUEUE_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created queue list. */
|
||||
|
||||
QUEUE_DECLARE TX_QUEUE * _tx_queue_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created queues. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_created_count;
|
||||
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of messages sent. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance_messages_sent_count;
|
||||
|
||||
|
||||
/* Define the total number of messages received. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance__messages_received_count;
|
||||
|
||||
|
||||
/* Define the total number of queue empty suspensions. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance_empty_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of queue full suspensions. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance_full_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of queue full errors. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance_full_error_count;
|
||||
|
||||
|
||||
/* Define the total number of queue timeouts. */
|
||||
|
||||
QUEUE_DECLARE ULONG _tx_queue_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post queue delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_QUEUE_DELETE_PORT_COMPLETION
|
||||
#define TX_QUEUE_DELETE_PORT_COMPLETION(q)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
144
common/inc/tx_semaphore.h
Normal file
144
common/inc/tx_semaphore.h
Normal file
@ -0,0 +1,144 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_semaphore.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX semaphore management component, */
|
||||
/* including all data types and external references. It is assumed */
|
||||
/* that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_SEMAPHORE_H
|
||||
#define TX_SEMAPHORE_H
|
||||
|
||||
|
||||
/* Define semaphore control specific data definitions. */
|
||||
|
||||
#define TX_SEMAPHORE_ID ((ULONG) 0x53454D41)
|
||||
|
||||
|
||||
/* Determine if in-line component initialization is supported by the
|
||||
caller. */
|
||||
#ifdef TX_INVOKE_INLINE_INITIALIZATION
|
||||
/* Yes, in-line initialization is supported, remap the
|
||||
semaphore initialization function. */
|
||||
#ifndef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
#define _tx_semaphore_initialize() \
|
||||
_tx_semaphore_created_ptr = TX_NULL; \
|
||||
_tx_semaphore_created_count = TX_EMPTY
|
||||
#else
|
||||
#define _tx_semaphore_initialize() \
|
||||
_tx_semaphore_created_ptr = TX_NULL; \
|
||||
_tx_semaphore_created_count = TX_EMPTY; \
|
||||
_tx_semaphore_performance_put_count = ((ULONG) 0); \
|
||||
_tx_semaphore_performance_get_count = ((ULONG) 0); \
|
||||
_tx_semaphore_performance_suspension_count = ((ULONG) 0); \
|
||||
_tx_semaphore_performance_timeout_count = ((ULONG) 0)
|
||||
#endif
|
||||
#define TX_SEMAPHORE_INIT
|
||||
#else
|
||||
/* No in-line initialization is supported, use standard
|
||||
function call. */
|
||||
VOID _tx_semaphore_initialize(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal semaphore management function prototypes. */
|
||||
|
||||
VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
|
||||
|
||||
|
||||
/* Semaphore management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_SEMAPHORE_INIT
|
||||
#define SEMAPHORE_DECLARE
|
||||
#else
|
||||
#define SEMAPHORE_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the head pointer of the created semaphore list. */
|
||||
|
||||
SEMAPHORE_DECLARE TX_SEMAPHORE * _tx_semaphore_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created semaphores. */
|
||||
|
||||
SEMAPHORE_DECLARE ULONG _tx_semaphore_created_count;
|
||||
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of semaphore puts. */
|
||||
|
||||
SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_put_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore gets. */
|
||||
|
||||
SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore suspensions. */
|
||||
|
||||
SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore timeouts. */
|
||||
|
||||
SEMAPHORE_DECLARE ULONG _tx_semaphore_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post semaphore delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_SEMAPHORE_DELETE_PORT_COMPLETION
|
||||
#define TX_SEMAPHORE_DELETE_PORT_COMPLETION(s)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
524
common/inc/tx_thread.h
Normal file
524
common/inc/tx_thread.h
Normal file
@ -0,0 +1,524 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_thread.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX thread control component, including */
|
||||
/* data types and external references. It is assumed that tx_api.h */
|
||||
/* and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_THREAD_H
|
||||
#define TX_THREAD_H
|
||||
|
||||
|
||||
/* Define thread control specific data definitions. */
|
||||
|
||||
#define TX_THREAD_ID ((ULONG) 0x54485244)
|
||||
#define TX_THREAD_PRIORITY_GROUP_MASK ((ULONG) 0xFF)
|
||||
#define TX_THREAD_EXECUTE_LOG_SIZE ((UINT) 8)
|
||||
|
||||
|
||||
/* Define the MOD32 bit set macro that is used to set/clear a priority bit within a specific
|
||||
priority group. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
#define MAP_INDEX (map_index)
|
||||
#ifndef TX_MOD32_BIT_SET
|
||||
#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)%((UINT)32)));
|
||||
#endif
|
||||
#else
|
||||
#define MAP_INDEX (0)
|
||||
#ifndef TX_MOD32_BIT_SET
|
||||
#define TX_MOD32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the DIV32 bit set macro that is used to set/clear a priority group bit and is
|
||||
only necessary when using priorities greater than 32. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
#ifndef TX_DIV32_BIT_SET
|
||||
#define TX_DIV32_BIT_SET(a,b) (b) = (((ULONG) 1) << ((a)/((UINT) 32)));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define state change macro that can be used by run-mode debug agents to keep track of thread
|
||||
state changes. By default, it is mapped to white space. */
|
||||
|
||||
#ifndef TX_THREAD_STATE_CHANGE
|
||||
#define TX_THREAD_STATE_CHANGE(a, b)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macro to get the current thread pointer. This is particularly useful in SMP
|
||||
versions of ThreadX to add additional processing. The default implementation is to simply
|
||||
access the global current thread pointer directly. */
|
||||
|
||||
#ifndef TX_THREAD_GET_CURRENT
|
||||
#define TX_THREAD_GET_CURRENT(a) (a) = _tx_thread_current_ptr;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macro to set the current thread pointer. This is particularly useful in SMP
|
||||
versions of ThreadX to add additional processing. The default implementation is to simply
|
||||
access the global current thread pointer directly. */
|
||||
|
||||
#ifndef TX_THREAD_SET_CURRENT
|
||||
#define TX_THREAD_SET_CURRENT(a) _tx_thread_current_ptr = (a);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the get system state macro. By default, it simply maps to the variable _tx_thread_system_state. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() _tx_thread_system_state
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
|
||||
indicates that _tx_thread_system_return should not be called. */
|
||||
|
||||
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
|
||||
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = (ULONG) _tx_thread_preempt_disable; (c) = (c) | TX_THREAD_GET_SYSTEM_STATE();
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the timeout setup macro used in _tx_thread_create. */
|
||||
|
||||
#ifndef TX_THREAD_CREATE_TIMEOUT_SETUP
|
||||
#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_timeout_param = TX_POINTER_TO_ULONG_CONVERT((t));
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the thread timeout pointer setup macro used in _tx_thread_timeout. */
|
||||
|
||||
#ifndef TX_THREAD_TIMEOUT_POINTER_SETUP
|
||||
#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = TX_ULONG_TO_THREAD_POINTER_CONVERT(timeout_input);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the lowest bit set macro. Note, that this may be overridden
|
||||
by a port specific definition if there is supporting assembly language
|
||||
instructions in the architecture. */
|
||||
|
||||
#ifndef TX_LOWEST_SET_BIT_CALCULATE
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) \
|
||||
(b) = ((ULONG) 0); \
|
||||
(m) = (m) & ((~(m)) + ((ULONG) 1)); \
|
||||
if ((m) < ((ULONG) 0x10)) \
|
||||
{ \
|
||||
if ((m) >= ((ULONG) 4)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 2); \
|
||||
(b) = (b) + ((ULONG) 2); \
|
||||
} \
|
||||
(b) = (b) + ((m) >> ((ULONG) 1)); \
|
||||
} \
|
||||
else if ((m) < ((ULONG) 0x100)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 4); \
|
||||
(b) = (b) + ((ULONG) 4); \
|
||||
if ((m) >= ((ULONG) 4)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 2); \
|
||||
(b) = (b) + ((ULONG) 2); \
|
||||
} \
|
||||
(b) = (b) + ((m) >> ((ULONG) 1)); \
|
||||
} \
|
||||
else if ((m) < ((ULONG) 0x10000)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 8); \
|
||||
(b) = (b) + ((ULONG) 8); \
|
||||
if ((m) >= ((ULONG) 0x10)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 4); \
|
||||
(b) = (b) + ((ULONG) 4); \
|
||||
} \
|
||||
if ((m) >= ((ULONG) 4)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 2); \
|
||||
(b) = (b) + ((ULONG) 2); \
|
||||
} \
|
||||
(b) = (b) + ((m) >> ((ULONG) 1)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 16); \
|
||||
(b) = (b) + ((ULONG) 16); \
|
||||
if ((m) >= ((ULONG) 0x100)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 8); \
|
||||
(b) = (b) + ((ULONG) 8); \
|
||||
} \
|
||||
if ((m) >= ((ULONG) 16)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 4); \
|
||||
(b) = (b) + ((ULONG) 4); \
|
||||
} \
|
||||
if ((m) >= ((ULONG) 4)) \
|
||||
{ \
|
||||
(m) = (m) >> ((ULONG) 2); \
|
||||
(b) = (b) + ((ULONG) 2); \
|
||||
} \
|
||||
(b) = (b) + ((m) >> ((ULONG) 1)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the default thread stack checking. This can be overridden by
|
||||
a particular port, which is necessary if the stack growth is from
|
||||
low address to high address (the default logic is for stacks that
|
||||
grow from high address to low address. */
|
||||
|
||||
#ifndef TX_THREAD_STACK_CHECK
|
||||
#define TX_THREAD_STACK_CHECK(thread_ptr) \
|
||||
{ \
|
||||
TX_INTERRUPT_SAVE_AREA \
|
||||
TX_DISABLE \
|
||||
if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID)) \
|
||||
{ \
|
||||
if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr)) \
|
||||
{ \
|
||||
(thread_ptr) -> tx_thread_stack_highest_ptr = (thread_ptr) -> tx_thread_stack_ptr; \
|
||||
} \
|
||||
if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) || \
|
||||
(*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) || \
|
||||
(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start))) \
|
||||
{ \
|
||||
TX_RESTORE \
|
||||
_tx_thread_stack_error_handler((thread_ptr)); \
|
||||
TX_DISABLE \
|
||||
} \
|
||||
if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL) \
|
||||
{ \
|
||||
TX_RESTORE \
|
||||
_tx_thread_stack_analyze((thread_ptr)); \
|
||||
TX_DISABLE \
|
||||
} \
|
||||
} \
|
||||
TX_RESTORE \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post thread delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_THREAD_DELETE_PORT_COMPLETION
|
||||
#define TX_THREAD_DELETE_PORT_COMPLETION(t)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post thread reset macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_THREAD_RESET_PORT_COMPLETION
|
||||
#define TX_THREAD_RESET_PORT_COMPLETION(t)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the thread create internal extension macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_THREAD_CREATE_INTERNAL_EXTENSION
|
||||
#define TX_THREAD_CREATE_INTERNAL_EXTENSION(t)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define internal thread control function prototypes. */
|
||||
|
||||
VOID _tx_thread_initialize(VOID);
|
||||
VOID _tx_thread_schedule(VOID);
|
||||
VOID _tx_thread_shell_entry(VOID);
|
||||
VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID));
|
||||
VOID _tx_thread_stack_error(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_stack_error_handler(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_system_preempt_check(VOID);
|
||||
VOID _tx_thread_system_resume(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_system_ni_resume(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_system_return(VOID);
|
||||
VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr);
|
||||
VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option);
|
||||
VOID _tx_thread_time_slice(VOID);
|
||||
VOID _tx_thread_timeout(ULONG timeout_input);
|
||||
|
||||
|
||||
/* Thread control component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#define THREAD_DECLARE extern
|
||||
|
||||
|
||||
/* Define the pointer that contains the system stack pointer. This is
|
||||
utilized when control returns from a thread to the system to reset the
|
||||
current stack. This is setup in the low-level initialization function. */
|
||||
|
||||
THREAD_DECLARE VOID * _tx_thread_system_stack_ptr;
|
||||
|
||||
|
||||
/* Define the current thread pointer. This variable points to the currently
|
||||
executing thread. If this variable is NULL, no thread is executing. */
|
||||
|
||||
THREAD_DECLARE TX_THREAD * _tx_thread_current_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the next thread to execute. It is important
|
||||
to remember that this is not necessarily equal to the current thread
|
||||
pointer. */
|
||||
|
||||
THREAD_DECLARE TX_THREAD * _tx_thread_execute_ptr;
|
||||
|
||||
|
||||
/* Define the head pointer of the created thread list. */
|
||||
|
||||
THREAD_DECLARE TX_THREAD * _tx_thread_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created threads. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_created_count;
|
||||
|
||||
|
||||
/* Define the current state variable. When this value is 0, a thread
|
||||
is executing or the system is idle. Other values indicate that
|
||||
interrupt or initialization processing is active. This variable is
|
||||
initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
|
||||
active. */
|
||||
|
||||
THREAD_DECLARE volatile ULONG _tx_thread_system_state;
|
||||
|
||||
|
||||
/* Define the 32-bit priority bit-maps. There is one priority bit map for each
|
||||
32 priority levels supported. If only 32 priorities are supported there is
|
||||
only one bit map. Each bit within a priority bit map represents that one
|
||||
or more threads at the associated thread priority are ready. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
|
||||
|
||||
|
||||
/* Define the priority map active bit map that specifies which of the previously
|
||||
defined priority maps have something set. This is only necessary if more than
|
||||
32 priorities are supported. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
THREAD_DECLARE ULONG _tx_thread_priority_map_active;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Define the 32-bit preempt priority bit maps. There is one preempt bit map
|
||||
for each 32 priority levels supported. If only 32 priorities are supported
|
||||
there is only one bit map. Each set set bit corresponds to a preempted priority
|
||||
level that had preemption-threshold active to protect against preemption of a
|
||||
range of relatively higher priority threads. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
|
||||
|
||||
|
||||
/* Define the preempt map active bit map that specifies which of the previously
|
||||
defined preempt maps have something set. This is only necessary if more than
|
||||
32 priorities are supported. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
THREAD_DECLARE ULONG _tx_thread_preempted_map_active;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define the variable that holds the highest priority group ready for
|
||||
execution. It is important to note that this is not necessarily the same
|
||||
as the priority of the thread pointed to by _tx_execute_thread. */
|
||||
|
||||
THREAD_DECLARE UINT _tx_thread_highest_priority;
|
||||
|
||||
|
||||
/* Define the array of thread pointers. Each entry represents the threads that
|
||||
are ready at that priority group. For example, index 10 in this array
|
||||
represents the first thread ready at priority 10. If this entry is NULL,
|
||||
no threads are ready at that priority. */
|
||||
|
||||
THREAD_DECLARE TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES];
|
||||
|
||||
|
||||
/* Define the global preempt disable variable. If this is non-zero, preemption is
|
||||
disabled. It is used internally by ThreadX to prevent preemption of a thread in
|
||||
the middle of a service that is resuming or suspending another thread. */
|
||||
|
||||
THREAD_DECLARE volatile UINT _tx_thread_preempt_disable;
|
||||
|
||||
|
||||
/* Define the global function pointer for mutex cleanup on thread completion or
|
||||
termination. This pointer is setup during mutex initialization. */
|
||||
|
||||
THREAD_DECLARE VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
|
||||
|
||||
|
||||
/* Define the global build options variable. This contains a bit map representing
|
||||
how the ThreadX library was built. The following are the bit field definitions:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
31 TX_NOT_INTERRUPTABLE defined
|
||||
30 TX_INLINE_THREAD_RESUME_SUSPEND define
|
||||
29-24 Priority groups 1 -> 32 priorities
|
||||
2 -> 64 priorities
|
||||
3 -> 96 priorities
|
||||
|
||||
...
|
||||
|
||||
32 -> 1024 priorities
|
||||
23 TX_TIMER_PROCESS_IN_ISR defined
|
||||
22 TX_REACTIVATE_INLINE defined
|
||||
21 TX_DISABLE_STACK_FILLING defined
|
||||
20 TX_ENABLE_STACK_CHECKING defined
|
||||
19 TX_DISABLE_PREEMPTION_THRESHOLD defined
|
||||
18 TX_DISABLE_REDUNDANT_CLEARING defined
|
||||
17 TX_DISABLE_NOTIFY_CALLBACKS defined
|
||||
16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
|
||||
15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
|
||||
14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
|
||||
13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
|
||||
12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
|
||||
11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
|
||||
10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined
|
||||
9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined
|
||||
8 TX_ENABLE_EVENT_TRACE defined
|
||||
7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
|
||||
6-0 Port Specific */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_build_options;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
|
||||
/* Define the global function pointer for stack error handling. If a stack error is
|
||||
detected and the application has registered a stack error handler, it will be
|
||||
called via this function pointer. */
|
||||
|
||||
THREAD_DECLARE VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of thread resumptions. Each time a thread enters the
|
||||
ready state this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_resume_count;
|
||||
|
||||
|
||||
/* Define the total number of thread suspensions. Each time a thread enters a
|
||||
suspended state this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_suspend_count;
|
||||
|
||||
|
||||
/* Define the total number of solicited thread preemptions. Each time a thread is
|
||||
preempted by directly calling a ThreadX service, this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_solicited_preemption_count;
|
||||
|
||||
|
||||
/* Define the total number of interrupt thread preemptions. Each time a thread is
|
||||
preempted as a result of an ISR calling a ThreadX service, this variable is
|
||||
incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_interrupt_preemption_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inversions. Each time a thread is blocked by
|
||||
a mutex owned by a lower-priority thread, this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_priority_inversion_count;
|
||||
|
||||
|
||||
/* Define the total number of time-slices. Each time a time-slice operation is
|
||||
actually performed (another thread is setup for running) this variable is
|
||||
incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_time_slice_count;
|
||||
|
||||
|
||||
/* Define the total number of thread relinquish operations. Each time a thread
|
||||
relinquish operation is actually performed (another thread is setup for running)
|
||||
this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_relinquish_count;
|
||||
|
||||
|
||||
/* Define the total number of thread timeouts. Each time a thread has a
|
||||
timeout this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_timeout_count;
|
||||
|
||||
|
||||
/* Define the total number of thread wait aborts. Each time a thread's suspension
|
||||
is lifted by the tx_thread_wait_abort call this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_wait_abort_count;
|
||||
|
||||
|
||||
/* Define the total number of idle system thread returns. Each time a thread returns to
|
||||
an idle system (no other thread is ready to run) this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_idle_return_count;
|
||||
|
||||
|
||||
/* Define the total number of non-idle system thread returns. Each time a thread returns to
|
||||
a non-idle system (another thread is ready to run) this variable is incremented. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance_non_idle_return_count;
|
||||
|
||||
|
||||
/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
|
||||
is a circular list, where the index points to the oldest entry. */
|
||||
|
||||
THREAD_DECLARE ULONG _tx_thread_performance__execute_log_index;
|
||||
THREAD_DECLARE TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
213
common/inc/tx_timer.h
Normal file
213
common/inc/tx_timer.h
Normal file
@ -0,0 +1,213 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Timer */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_timer.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX timer management component, including */
|
||||
/* data types and external references. It is assumed that tx_api.h */
|
||||
/* and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_TIMER_H
|
||||
#define TX_TIMER_H
|
||||
|
||||
|
||||
/* Define timer management specific data definitions. */
|
||||
|
||||
#define TX_TIMER_ID ((ULONG) 0x4154494D)
|
||||
#define TX_TIMER_ENTRIES ((ULONG) 32)
|
||||
|
||||
|
||||
/* Define internal timer management function prototypes. */
|
||||
|
||||
VOID _tx_timer_expiration_process(VOID);
|
||||
VOID _tx_timer_initialize(VOID);
|
||||
VOID _tx_timer_system_activate(TX_TIMER_INTERNAL *timer_ptr);
|
||||
VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr);
|
||||
VOID _tx_timer_thread_entry(ULONG timer_thread_input);
|
||||
|
||||
|
||||
/* Timer management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_TIMER_INIT
|
||||
#define TIMER_DECLARE
|
||||
#else
|
||||
#define TIMER_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system clock value that is continually incremented by the
|
||||
periodic timer interrupt processing. */
|
||||
|
||||
TIMER_DECLARE volatile ULONG _tx_timer_system_clock;
|
||||
|
||||
|
||||
/* Define the current time slice value. If non-zero, a time-slice is active.
|
||||
Otherwise, the time_slice is not active. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_time_slice;
|
||||
|
||||
|
||||
/* Define the time-slice expiration flag. This is used to indicate that a time-slice
|
||||
has happened. */
|
||||
|
||||
TIMER_DECLARE UINT _tx_timer_expired_time_slice;
|
||||
|
||||
|
||||
/* Define the thread and application timer entry list. This list provides a direct access
|
||||
method for insertion of times less than TX_TIMER_ENTRIES. */
|
||||
|
||||
TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES];
|
||||
|
||||
|
||||
/* Define the boundary pointers to the list. These are setup to easily manage
|
||||
wrapping the list. */
|
||||
|
||||
TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_start;
|
||||
TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_list_end;
|
||||
|
||||
|
||||
/* Define the current timer pointer in the list. This pointer is moved sequentially
|
||||
through the timer list by the timer interrupt handler. */
|
||||
|
||||
TIMER_DECLARE TX_TIMER_INTERNAL **_tx_timer_current_ptr;
|
||||
|
||||
|
||||
/* Define the timer expiration flag. This is used to indicate that a timer
|
||||
has expired. */
|
||||
|
||||
TIMER_DECLARE UINT _tx_timer_expired;
|
||||
|
||||
|
||||
/* Define the created timer list head pointer. */
|
||||
|
||||
TIMER_DECLARE TX_TIMER *_tx_timer_created_ptr;
|
||||
|
||||
|
||||
/* Define the created timer count. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_created_count;
|
||||
|
||||
|
||||
/* Define the pointer to the timer that has expired and is being processed. */
|
||||
|
||||
TIMER_DECLARE TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr;
|
||||
|
||||
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
|
||||
/* Define the timer thread's control block. */
|
||||
|
||||
TIMER_DECLARE TX_THREAD _tx_timer_thread;
|
||||
|
||||
|
||||
/* Define the variable that holds the timer thread's starting stack address. */
|
||||
|
||||
TIMER_DECLARE VOID *_tx_timer_stack_start;
|
||||
|
||||
|
||||
/* Define the variable that holds the timer thread's stack size. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_stack_size;
|
||||
|
||||
|
||||
/* Define the variable that holds the timer thread's priority. */
|
||||
|
||||
TIMER_DECLARE UINT _tx_timer_priority;
|
||||
|
||||
/* Define the system timer thread's stack. The default size is defined
|
||||
in tx_port.h. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG)) - ((UINT) 1)))/sizeof(ULONG)];
|
||||
|
||||
#else
|
||||
|
||||
|
||||
/* Define the busy flag that will prevent nested timer ISR processing. */
|
||||
|
||||
TIMER_DECLARE UINT _tx_timer_processing_active;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of timer activations. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_performance_activate_count;
|
||||
|
||||
|
||||
/* Define the total number of timer reactivations. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_performance_reactivate_count;
|
||||
|
||||
|
||||
/* Define the total number of timer deactivations. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_performance_deactivate_count;
|
||||
|
||||
|
||||
/* Define the total number of timer expirations. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_performance_expiration_count;
|
||||
|
||||
|
||||
/* Define the total number of timer expiration adjustments. These are required
|
||||
if the expiration time is greater than the size of the timer list. In such
|
||||
cases, the timer is placed at the end of the list and then reactivated
|
||||
as many times as necessary to finally achieve the resulting timeout. */
|
||||
|
||||
TIMER_DECLARE ULONG _tx_timer_performance__expiration_adjust_count;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define default post timer delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h). */
|
||||
|
||||
#ifndef TX_TIMER_DELETE_PORT_COMPLETION
|
||||
#define TX_TIMER_DELETE_PORT_COMPLETION(t)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
559
common/inc/tx_trace.h
Normal file
559
common/inc/tx_trace.h
Normal file
@ -0,0 +1,559 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Trace */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT DEFINITION RELEASE */
|
||||
/* */
|
||||
/* tx_trace.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the ThreadX trace component, including constants */
|
||||
/* and structure definitions as well as external references. It is */
|
||||
/* assumed that tx_api.h and tx_port.h have already been included. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#ifndef TX_TRACE_H
|
||||
#define TX_TRACE_H
|
||||
|
||||
|
||||
/* Determine if tracing is enabled. If not, simply define the in-line trace
|
||||
macros to whitespace. */
|
||||
|
||||
#ifndef TX_ENABLE_EVENT_TRACE
|
||||
#define TX_TRACE_INITIALIZE
|
||||
#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b)
|
||||
#define TX_TRACE_OBJECT_UNREGISTER(o)
|
||||
#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,f)
|
||||
#else
|
||||
|
||||
/* Event tracing is enabled. */
|
||||
|
||||
/* Ensure that the thread component information is included. */
|
||||
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/* Define trace port-specfic extension to white space if it isn't defined
|
||||
already. */
|
||||
|
||||
#ifndef TX_TRACE_PORT_EXTENSION
|
||||
#define TX_TRACE_PORT_EXTENSION
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the default clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the ID showing the event trace buffer is valid. */
|
||||
|
||||
#define TX_TRACE_VALID 0x54585442UL
|
||||
|
||||
|
||||
/* ThreadX Trace Description. The ThreadX Trace feature is designed to capture
|
||||
events in real-time in a circular event buffer. This buffer may be analyzed by other
|
||||
tools. The high-level format of the Trace structure is:
|
||||
|
||||
[Trace Control Header ]
|
||||
[Trace Object Registry - Entry 0 ]
|
||||
...
|
||||
[Trace Object Registry - Entry "n" ]
|
||||
[Trace Buffer - Entry 0 ]
|
||||
...
|
||||
[Trace Buffer - Entry "n" ]
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Trace Control Header. The Trace Control Header contains information that
|
||||
defines the format of the Trace Object Registry as well as the location and
|
||||
current entry of the Trace Buffer itself. The high-level format of the
|
||||
Trace Control Header is:
|
||||
|
||||
Entry Size Description
|
||||
|
||||
[Trace ID] 4 This 4-byte field contains the ThreadX Trace
|
||||
Identification. If the trace buffer is valid, the
|
||||
contents are 0x54585442 (TXTB). Since it is written as
|
||||
a 32-bit unsigned word, this value is also used to
|
||||
determine if the event trace information is in
|
||||
little or big endian format.
|
||||
[Timer Valid Mask] 4 Mask of valid bits in the 32-bit time stamp. This
|
||||
enables use of 32, 24, 16, or event 8-bit timers.
|
||||
If the time source is 32-bits, the mask is
|
||||
0xFFFFFFFF. If the time source is 16-bits, the
|
||||
mask is 0x0000FFFF.
|
||||
[Trace Base Address] 4 The base address for all trace pointer. Subtracting
|
||||
the pointer and this address will yield the proper
|
||||
offset into the trace buffer.
|
||||
[Trace Object Registry Start Pointer] 4 Pointer to the start of Trace Object Registry
|
||||
[Reserved] 2 Reserved two bytes - should be 0x0000
|
||||
[Trace Object Object Name Size] 2 Number of bytes in object name
|
||||
[Trace Object Registry End Pointer] 4 Pointer to the end of Trace Object Registry
|
||||
[Trace Buffer Start Pointer] 4 Pointer to the start of the Trace Buffer Area
|
||||
[Trace Buffer End Pointer] 4 Pointer to the end of the Trace Buffer Area
|
||||
[Trace Buffer Current Pointer] 4 Pointer to the oldest entry in the Trace Buffer.
|
||||
This entry will be overwritten on the next event and
|
||||
incremented to the next event (wrapping to the top
|
||||
if the buffer end pointer is exceeded).
|
||||
[Reserved] 4 Reserved 4 bytes, should be 0xAAAAAAAA
|
||||
[Reserved] 4 Reserved 4 bytes, should be 0xBBBBBBBB
|
||||
[Reserved] 4 Reserved 4 bytes, should be 0xCCCCCCCC
|
||||
*/
|
||||
|
||||
|
||||
/* Define the Trace Control Header. */
|
||||
|
||||
typedef struct TX_TRACE_HEADER_STRUCT
|
||||
{
|
||||
|
||||
ULONG tx_trace_header_id;
|
||||
ULONG tx_trace_header_timer_valid_mask;
|
||||
ULONG tx_trace_header_trace_base_address;
|
||||
ULONG tx_trace_header_registry_start_pointer;
|
||||
USHORT tx_trace_header_reserved1;
|
||||
USHORT tx_trace_header_object_name_size;
|
||||
ULONG tx_trace_header_registry_end_pointer;
|
||||
ULONG tx_trace_header_buffer_start_pointer;
|
||||
ULONG tx_trace_header_buffer_end_pointer;
|
||||
ULONG tx_trace_header_buffer_current_pointer;
|
||||
ULONG tx_trace_header_reserved2;
|
||||
ULONG tx_trace_header_reserved3;
|
||||
ULONG tx_trace_header_reserved4;
|
||||
} TX_TRACE_HEADER;
|
||||
|
||||
|
||||
/* Trace Object Registry. The Trace Object Registry is used to map the object pointer in the trace buffer to
|
||||
the application's name for the object (defined during object creation in ThreadX). */
|
||||
|
||||
#ifndef TX_TRACE_OBJECT_REGISTRY_NAME
|
||||
#define TX_TRACE_OBJECT_REGISTRY_NAME 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the object name types as well as the contents of any additional parameters that might be useful in
|
||||
trace analysis. */
|
||||
|
||||
#define TX_TRACE_OBJECT_TYPE_NOT_VALID ((UCHAR) 0) /* Object is not valid */
|
||||
#define TX_TRACE_OBJECT_TYPE_THREAD ((UCHAR) 1) /* P1 = stack start address, P2 = stack size */
|
||||
#define TX_TRACE_OBJECT_TYPE_TIMER ((UCHAR) 2) /* P1 = initial ticks, P2 = reschedule ticks */
|
||||
#define TX_TRACE_OBJECT_TYPE_QUEUE ((UCHAR) 3) /* P1 = queue size, P2 = message size */
|
||||
#define TX_TRACE_OBJECT_TYPE_SEMAPHORE ((UCHAR) 4) /* P1 = initial instances */
|
||||
#define TX_TRACE_OBJECT_TYPE_MUTEX ((UCHAR) 5) /* P1 = priority inheritance flag */
|
||||
#define TX_TRACE_OBJECT_TYPE_EVENT_FLAGS ((UCHAR) 6) /* none */
|
||||
#define TX_TRACE_OBJECT_TYPE_BLOCK_POOL ((UCHAR) 7) /* P1 = total blocks, P2 = block size */
|
||||
#define TX_TRACE_OBJECT_TYPE_BYTE_POOL ((UCHAR) 8) /* P1 = total bytes */
|
||||
|
||||
|
||||
typedef struct TX_TRACE_OBJECT_ENTRY_STRUCT
|
||||
{
|
||||
|
||||
UCHAR tx_trace_object_entry_available; /* TX_TRUE -> available */
|
||||
UCHAR tx_trace_object_entry_type; /* Types defined above */
|
||||
UCHAR tx_trace_object_entry_reserved1; /* Should be zero - except for thread */
|
||||
UCHAR tx_trace_object_entry_reserved2; /* Should be zero - except for thread */
|
||||
ULONG tx_trace_object_entry_thread_pointer; /* ThreadX object pointer */
|
||||
ULONG tx_trace_object_entry_param_1; /* Parameter value defined */
|
||||
ULONG tx_trace_object_entry_param_2; /* according to type above */
|
||||
UCHAR tx_trace_object_entry_name[TX_TRACE_OBJECT_REGISTRY_NAME]; /* Object name */
|
||||
} TX_TRACE_OBJECT_ENTRY;
|
||||
|
||||
|
||||
/* Trace Buffer Entry. The Trace Buffer Entry contains information about a particular
|
||||
event in the system. The high-level format of the Trace Buffer Entry is:
|
||||
|
||||
Entry Size Description
|
||||
|
||||
[Thread Pointer] 4 This 4-byte field contains the pointer to the
|
||||
ThreadX thread running that caused the event.
|
||||
If this field is NULL, the entry hasn't been used
|
||||
yet. If this field is 0xFFFFFFFF, the event occurred
|
||||
from within an ISR. If this entry is 0xF0F0F0F0, the
|
||||
event occurred during initialization.
|
||||
[Thread Priority or 4 This 4-byte field contains the current thread pointer for interrupt
|
||||
Current Thread events or the thread preemption-threshold/priority for thread events.
|
||||
Preemption-Threshold/
|
||||
Priority]
|
||||
[Event ID] 4 This 4-byte field contains the Event ID of the event. A value of
|
||||
0xFFFFFFFF indicates the event is invalid. All events are marked
|
||||
as invalid during initialization.
|
||||
[Time Stamp] 4 This 4-byte field contains the time stamp of the event.
|
||||
[Information Field 1] 4 This 4-byte field contains the first 4-bytes of information
|
||||
specific to the event.
|
||||
[Information Field 2] 4 This 4-byte field contains the second 4-bytes of information
|
||||
specific to the event.
|
||||
[Information Field 3] 4 This 4-byte field contains the third 4-bytes of information
|
||||
specific to the event.
|
||||
[Information Field 4] 4 This 4-byte field contains the fourth 4-bytes of information
|
||||
specific to the event.
|
||||
*/
|
||||
|
||||
#define TX_TRACE_INVALID_EVENT 0xFFFFFFFFUL
|
||||
|
||||
|
||||
/* Define ThreadX Trace Events, along with a brief description of the additional information fields,
|
||||
where I1 -> Information Field 1, I2 -> Information Field 2, etc. */
|
||||
|
||||
/* Event numbers 0 through 4095 are reserved by Express Logic. Specific event assignments are:
|
||||
|
||||
ThreadX events: 1-199
|
||||
FileX events: 200-299
|
||||
NetX events: 300-599
|
||||
USBX events: 600-999
|
||||
|
||||
User-defined event numbers start at 4096 and continue through 65535, as defined by the constants
|
||||
TX_TRACE_USER_EVENT_START and TX_TRACE_USER_EVENT_END, respectively. User events should be based
|
||||
on these constants in case the user event number assignment is changed in future releases. */
|
||||
|
||||
/* Define the basic ThreadX thread scheduling events first. */
|
||||
|
||||
#define TX_TRACE_THREAD_RESUME 1 /* I1 = thread ptr, I2 = previous_state, I3 = stack ptr, I4 = next thread */
|
||||
#define TX_TRACE_THREAD_SUSPEND 2 /* I1 = thread ptr, I2 = new_state, I3 = stack ptr I4 = next thread */
|
||||
#define TX_TRACE_ISR_ENTER 3 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
|
||||
#define TX_TRACE_ISR_EXIT 4 /* I1 = stack_ptr, I2 = ISR number, I3 = system state, I4 = preempt disable */
|
||||
#define TX_TRACE_TIME_SLICE 5 /* I1 = next thread ptr, I2 = system state, I3 = preempt disable, I4 = stack*/
|
||||
#define TX_TRACE_RUNNING 6 /* None */
|
||||
|
||||
|
||||
/* Define the rest of the ThreadX system events. */
|
||||
|
||||
#define TX_TRACE_BLOCK_ALLOCATE 10 /* I1 = pool ptr, I2 = memory ptr, I3 = wait option, I4 = remaining blocks */
|
||||
#define TX_TRACE_BLOCK_POOL_CREATE 11 /* I1 = pool ptr, I2 = pool_start, I3 = total blocks, I4 = block size */
|
||||
#define TX_TRACE_BLOCK_POOL_DELETE 12 /* I1 = pool ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_BLOCK_POOL_INFO_GET 13 /* I1 = pool ptr */
|
||||
#define TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET 14 /* I1 = pool ptr */
|
||||
#define TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET 15 /* None */
|
||||
#define TX_TRACE_BLOCK_POOL_PRIORITIZE 16 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
|
||||
#define TX_TRACE_BLOCK_RELEASE 17 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = stack ptr */
|
||||
#define TX_TRACE_BYTE_ALLOCATE 20 /* I1 = pool ptr, I2 = memory ptr, I3 = size requested, I4 = wait option */
|
||||
#define TX_TRACE_BYTE_POOL_CREATE 21 /* I1 = pool ptr, I2 = start ptr, I3 = pool size, I4 = stack ptr */
|
||||
#define TX_TRACE_BYTE_POOL_DELETE 22 /* I1 = pool ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_BYTE_POOL_INFO_GET 23 /* I1 = pool ptr */
|
||||
#define TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET 24 /* I1 = pool ptr */
|
||||
#define TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET 25 /* None */
|
||||
#define TX_TRACE_BYTE_POOL_PRIORITIZE 26 /* I1 = pool ptr, I2 = suspended count, I3 = stack ptr */
|
||||
#define TX_TRACE_BYTE_RELEASE 27 /* I1 = pool ptr, I2 = memory ptr, I3 = suspended, I4 = available bytes */
|
||||
#define TX_TRACE_EVENT_FLAGS_CREATE 30 /* I1 = group ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_EVENT_FLAGS_DELETE 31 /* I1 = group ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_EVENT_FLAGS_GET 32 /* I1 = group ptr, I2 = requested flags, I3 = current flags, I4 = get option*/
|
||||
#define TX_TRACE_EVENT_FLAGS_INFO_GET 33 /* I1 = group ptr */
|
||||
#define TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET 34 /* I1 = group ptr */
|
||||
#define TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET 35 /* None */
|
||||
#define TX_TRACE_EVENT_FLAGS_SET 36 /* I1 = group ptr, I2 = flags to set, I3 = set option, I4= suspended count */
|
||||
#define TX_TRACE_EVENT_FLAGS_SET_NOTIFY 37 /* I1 = group ptr */
|
||||
#define TX_TRACE_INTERRUPT_CONTROL 40 /* I1 = new interrupt posture, I2 = stack ptr */
|
||||
#define TX_TRACE_MUTEX_CREATE 50 /* I1 = mutex ptr, I2 = inheritance, I3 = stack ptr */
|
||||
#define TX_TRACE_MUTEX_DELETE 51 /* I1 = mutex ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_MUTEX_GET 52 /* I1 = mutex ptr, I2 = wait option, I3 = owning thread, I4 = own count */
|
||||
#define TX_TRACE_MUTEX_INFO_GET 53 /* I1 = mutex ptr */
|
||||
#define TX_TRACE_MUTEX_PERFORMANCE_INFO_GET 54 /* I1 = mutex ptr */
|
||||
#define TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET 55 /* None */
|
||||
#define TX_TRACE_MUTEX_PRIORITIZE 56 /* I1 = mutex ptr, I2 = suspended count, I3 = stack ptr */
|
||||
#define TX_TRACE_MUTEX_PUT 57 /* I1 = mutex ptr, I2 = owning thread, I3 = own count, I4 = stack ptr */
|
||||
#define TX_TRACE_QUEUE_CREATE 60 /* I1 = queue ptr, I2 = message size, I3 = queue start, I4 = queue size */
|
||||
#define TX_TRACE_QUEUE_DELETE 61 /* I1 = queue ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_QUEUE_FLUSH 62 /* I1 = queue ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_QUEUE_FRONT_SEND 63 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
|
||||
#define TX_TRACE_QUEUE_INFO_GET 64 /* I1 = queue ptr */
|
||||
#define TX_TRACE_QUEUE_PERFORMANCE_INFO_GET 65 /* I1 = queue ptr */
|
||||
#define TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET 66 /* None */
|
||||
#define TX_TRACE_QUEUE_PRIORITIZE 67 /* I1 = queue ptr, I2 = suspended count, I3 = stack ptr */
|
||||
#define TX_TRACE_QUEUE_RECEIVE 68 /* I1 = queue ptr, I2 = destination ptr, I3 = wait option, I4 = enqueued */
|
||||
#define TX_TRACE_QUEUE_SEND 69 /* I1 = queue ptr, I2 = source ptr, I3 = wait option, I4 = enqueued */
|
||||
#define TX_TRACE_QUEUE_SEND_NOTIFY 70 /* I1 = queue ptr */
|
||||
#define TX_TRACE_SEMAPHORE_CEILING_PUT 80 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4 =ceiling */
|
||||
#define TX_TRACE_SEMAPHORE_CREATE 81 /* I1 = semaphore ptr, I2 = initial count, I3 = stack ptr */
|
||||
#define TX_TRACE_SEMAPHORE_DELETE 82 /* I1 = semaphore ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_SEMAPHORE_GET 83 /* I1 = semaphore ptr, I2 = wait option, I3 = current count, I4 = stack ptr */
|
||||
#define TX_TRACE_SEMAPHORE_INFO_GET 84 /* I1 = semaphore ptr */
|
||||
#define TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET 85 /* I1 = semaphore ptr */
|
||||
#define TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET 86 /* None */
|
||||
#define TX_TRACE_SEMAPHORE_PRIORITIZE 87 /* I1 = semaphore ptr, I2 = suspended count, I2 = stack ptr */
|
||||
#define TX_TRACE_SEMAPHORE_PUT 88 /* I1 = semaphore ptr, I2 = current count, I3 = suspended count,I4=stack ptr*/
|
||||
#define TX_TRACE_SEMAPHORE_PUT_NOTIFY 89 /* I1 = semaphore ptr */
|
||||
#define TX_TRACE_THREAD_CREATE 100 /* I1 = thread ptr, I2 = priority, I3 = stack ptr, I4 = stack_size */
|
||||
#define TX_TRACE_THREAD_DELETE 101 /* I1 = thread ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY 102 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_THREAD_IDENTIFY 103 /* None */
|
||||
#define TX_TRACE_THREAD_INFO_GET 104 /* I1 = thread ptr, I2 = thread state */
|
||||
#define TX_TRACE_THREAD_PERFORMANCE_INFO_GET 105 /* I1 = thread ptr, I2 = thread state */
|
||||
#define TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET 106 /* None */
|
||||
#define TX_TRACE_THREAD_PREEMPTION_CHANGE 107 /* I1 = thread ptr, I2 = new threshold, I3 = old threshold, I4 =thread state*/
|
||||
#define TX_TRACE_THREAD_PRIORITY_CHANGE 108 /* I1 = thread ptr, I2 = new priority, I3 = old priority, I4 = thread state */
|
||||
#define TX_TRACE_THREAD_RELINQUISH 109 /* I1 = stack ptr, I2 = next thread ptr */
|
||||
#define TX_TRACE_THREAD_RESET 110 /* I1 = thread ptr, I2 = thread state */
|
||||
#define TX_TRACE_THREAD_RESUME_API 111 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_THREAD_SLEEP 112 /* I1 = sleep value, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_THREAD_STACK_ERROR_NOTIFY 113 /* None */
|
||||
#define TX_TRACE_THREAD_SUSPEND_API 114 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_THREAD_TERMINATE 115 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_THREAD_TIME_SLICE_CHANGE 116 /* I1 = thread ptr, I2 = new timeslice, I3 = old timeslice */
|
||||
#define TX_TRACE_THREAD_WAIT_ABORT 117 /* I1 = thread ptr, I2 = thread state, I3 = stack ptr */
|
||||
#define TX_TRACE_TIME_GET 120 /* I1 = current time, I2 = stack ptr */
|
||||
#define TX_TRACE_TIME_SET 121 /* I1 = new time */
|
||||
#define TX_TRACE_TIMER_ACTIVATE 122 /* I1 = timer ptr */
|
||||
#define TX_TRACE_TIMER_CHANGE 123 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks */
|
||||
#define TX_TRACE_TIMER_CREATE 124 /* I1 = timer ptr, I2 = initial ticks, I3= reschedule ticks, I4 = enable */
|
||||
#define TX_TRACE_TIMER_DEACTIVATE 125 /* I1 = timer ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_TIMER_DELETE 126 /* I1 = timer ptr */
|
||||
#define TX_TRACE_TIMER_INFO_GET 127 /* I1 = timer ptr, I2 = stack ptr */
|
||||
#define TX_TRACE_TIMER_PERFORMANCE_INFO_GET 128 /* I1 = timer ptr */
|
||||
#define TX_TRACE_TIMER_PERFORMANCE_SYSTEM_INFO_GET 129 /* None */
|
||||
|
||||
|
||||
/* Define the an Trace Buffer Entry. */
|
||||
|
||||
typedef struct TX_TRACE_BUFFER_ENTRY_STRUCT
|
||||
{
|
||||
|
||||
ULONG tx_trace_buffer_entry_thread_pointer;
|
||||
ULONG tx_trace_buffer_entry_thread_priority;
|
||||
ULONG tx_trace_buffer_entry_event_id;
|
||||
ULONG tx_trace_buffer_entry_time_stamp;
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
ULONG tx_trace_buffer_entry_info_1;
|
||||
ULONG tx_trace_buffer_entry_info_2;
|
||||
ULONG tx_trace_buffer_entry_info_3;
|
||||
ULONG tx_trace_buffer_entry_info_4;
|
||||
#else
|
||||
ULONG tx_trace_buffer_entry_information_field_1;
|
||||
ULONG tx_trace_buffer_entry_information_field_2;
|
||||
ULONG tx_trace_buffer_entry_information_field_3;
|
||||
ULONG tx_trace_buffer_entry_information_field_4;
|
||||
#endif
|
||||
} TX_TRACE_BUFFER_ENTRY;
|
||||
|
||||
|
||||
/* Trace management component data declarations follow. */
|
||||
|
||||
/* Determine if the initialization function of this component is including
|
||||
this file. If so, make the data definitions really happen. Otherwise,
|
||||
make them extern so other functions in the component can access them. */
|
||||
|
||||
#ifdef TX_TRACE_INIT
|
||||
#define TRACE_DECLARE
|
||||
#else
|
||||
#define TRACE_DECLARE extern
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the pointer to the start of the trace buffer control structure. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_HEADER *_tx_trace_header_ptr;
|
||||
|
||||
|
||||
/* Define the pointer to the start of the trace object registry area in the trace buffer. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_start_ptr;
|
||||
|
||||
|
||||
/* Define the pointer to the end of the trace object registry area in the trace buffer. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_OBJECT_ENTRY *_tx_trace_registry_end_ptr;
|
||||
|
||||
|
||||
/* Define the pointer to the starting entry of the actual trace event area of the trace buffer. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr;
|
||||
|
||||
|
||||
/* Define the pointer to the ending entry of the actual trace event area of the trace buffer. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr;
|
||||
|
||||
|
||||
/* Define the pointer to the current entry of the actual trace event area of the trace buffer. */
|
||||
|
||||
TRACE_DECLARE TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr;
|
||||
|
||||
|
||||
/* Define the trace event enable bits, where each bit represents a type of event that can be enabled
|
||||
or disabled dynamically by the application. */
|
||||
|
||||
TRACE_DECLARE ULONG _tx_trace_event_enable_bits;
|
||||
|
||||
|
||||
/* Define a counter that is used in environments that don't have a timer source. This counter
|
||||
is incremented on each use giving each event a unique timestamp. */
|
||||
|
||||
TRACE_DECLARE ULONG _tx_trace_simulated_time;
|
||||
|
||||
|
||||
/* Define the function pointer used to call the application when the trace buffer wraps. If NULL,
|
||||
the application has not registered a callback function. */
|
||||
|
||||
TRACE_DECLARE VOID (*_tx_trace_full_notify_function)(VOID *buffer);
|
||||
|
||||
|
||||
/* Define the total number of registry entries. */
|
||||
|
||||
TRACE_DECLARE ULONG _tx_trace_total_registry_entries;
|
||||
|
||||
|
||||
/* Define a counter that is used to track the number of available registry entries. */
|
||||
|
||||
TRACE_DECLARE ULONG _tx_trace_available_registry_entries;
|
||||
|
||||
|
||||
/* Define an index that represents the start of the registry search. */
|
||||
|
||||
TRACE_DECLARE ULONG _tx_trace_registry_search_start;
|
||||
|
||||
|
||||
/* Define the event trace macros that are expanded in-line when event tracing is enabled. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (d);
|
||||
#else
|
||||
#define TX_TRACE_INFO_FIELD_ASSIGNMENT(a,b,c,d) trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (a); trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (b); trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (c); trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (d);
|
||||
#endif
|
||||
|
||||
|
||||
#define TX_TRACE_INITIALIZE _tx_trace_initialize();
|
||||
#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (CHAR *) (n), (ULONG) (a), (ULONG) (b));
|
||||
#define TX_TRACE_OBJECT_UNREGISTER(o) _tx_trace_object_unregister((VOID *) (o));
|
||||
#ifndef TX_TRACE_IN_LINE_INSERT
|
||||
#define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) \
|
||||
{ \
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event_ptr; \
|
||||
ULONG trace_system_state; \
|
||||
ULONG trace_priority; \
|
||||
TX_THREAD *trace_thread_ptr; \
|
||||
trace_event_ptr = _tx_trace_buffer_current_ptr; \
|
||||
if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (e)))) \
|
||||
{ \
|
||||
TX_TRACE_PORT_EXTENSION \
|
||||
trace_system_state = (ULONG) TX_THREAD_GET_SYSTEM_STATE(); \
|
||||
TX_THREAD_GET_CURRENT(trace_thread_ptr) \
|
||||
\
|
||||
if (trace_system_state == 0) \
|
||||
{ \
|
||||
trace_priority = trace_thread_ptr -> tx_thread_priority; \
|
||||
trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16); \
|
||||
} \
|
||||
else if (trace_system_state < 0xF0F0F0F0UL) \
|
||||
{ \
|
||||
trace_priority = (ULONG) trace_thread_ptr; \
|
||||
trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL; \
|
||||
trace_priority = 0; \
|
||||
} \
|
||||
trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr; \
|
||||
trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority; \
|
||||
trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (i); \
|
||||
trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) TX_TRACE_TIME_SOURCE; \
|
||||
TX_TRACE_INFO_FIELD_ASSIGNMENT((a),(b),(c),(d)) \
|
||||
trace_event_ptr++; \
|
||||
if (trace_event_ptr >= _tx_trace_buffer_end_ptr) \
|
||||
{ \
|
||||
trace_event_ptr = _tx_trace_buffer_start_ptr; \
|
||||
_tx_trace_buffer_current_ptr = trace_event_ptr; \
|
||||
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
|
||||
if (_tx_trace_full_notify_function) \
|
||||
(_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_tx_trace_buffer_current_ptr = trace_event_ptr; \
|
||||
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_SOURCE_CODE
|
||||
|
||||
/* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */
|
||||
|
||||
VOID _tx_trace_initialize(VOID);
|
||||
VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2);
|
||||
VOID _tx_trace_object_unregister(VOID *object_ptr);
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* Check for MISRA compliance requirements. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
|
||||
/* Define MISRA-specific routines. */
|
||||
|
||||
UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer);
|
||||
TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer);
|
||||
TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer);
|
||||
TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer);
|
||||
UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer);
|
||||
|
||||
|
||||
#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_object_to_uchar_pointer_convert((a))
|
||||
#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) _tx_misra_uchar_to_object_pointer_convert((a))
|
||||
#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) _tx_misra_uchar_to_header_pointer_convert((a))
|
||||
#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) _tx_misra_uchar_to_entry_pointer_convert((a))
|
||||
#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_entry_to_uchar_pointer_convert((a))
|
||||
|
||||
#else
|
||||
|
||||
#define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
|
||||
#define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) ((TX_TRACE_OBJECT_ENTRY *) ((VOID *) (a)))
|
||||
#define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) ((TX_TRACE_HEADER *) ((VOID *) (a)))
|
||||
#define TX_UCHAR_TO_ENTRY_POINTER_CONVERT(a) ((TX_TRACE_BUFFER_ENTRY *) ((VOID *) (a)))
|
||||
#define TX_ENTRY_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a)))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
257
common/inc/tx_user_sample.h
Normal file
257
common/inc/tx_user_sample.h
Normal file
@ -0,0 +1,257 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** User Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_user.h PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains user defines for configuring ThreadX in specific */
|
||||
/* ways. This file will have an effect only if the application and */
|
||||
/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */
|
||||
/* Note that all the defines in this file may also be made on the */
|
||||
/* command line when building ThreadX library and application objects. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_USER_H
|
||||
#define TX_USER_H
|
||||
|
||||
|
||||
/* Define various build options for the ThreadX port. The application should either make changes
|
||||
here by commenting or un-commenting the conditional compilation defined OR supply the defines
|
||||
though the compiler's equivalent of the -D option.
|
||||
|
||||
For maximum speed, the following should be defined:
|
||||
|
||||
TX_MAX_PRIORITIES 32
|
||||
TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
TX_DISABLE_REDUNDANT_CLEARING
|
||||
TX_DISABLE_NOTIFY_CALLBACKS
|
||||
TX_NOT_INTERRUPTABLE
|
||||
TX_TIMER_PROCESS_IN_ISR
|
||||
TX_REACTIVATE_INLINE
|
||||
TX_DISABLE_STACK_FILLING
|
||||
TX_INLINE_THREAD_RESUME_SUSPEND
|
||||
|
||||
For minimum size, the following should be defined:
|
||||
|
||||
TX_MAX_PRIORITIES 32
|
||||
TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
TX_DISABLE_REDUNDANT_CLEARING
|
||||
TX_DISABLE_NOTIFY_CALLBACKS
|
||||
TX_NOT_INTERRUPTABLE
|
||||
TX_TIMER_PROCESS_IN_ISR
|
||||
|
||||
Of course, many of these defines reduce functionality and/or change the behavior of the
|
||||
system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR
|
||||
results in faster and smaller code, however, it increases the amount of processing in the ISR.
|
||||
In addition, some services that are available in timers are not available from ISRs and will
|
||||
therefore return an error if this option is used. This may or may not be desirable for a
|
||||
given application. */
|
||||
|
||||
|
||||
/* Override various options with default values already assigned in tx_port.h. Please also refer
|
||||
to tx_port.h for descriptions on each of these options. */
|
||||
|
||||
/*
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#define TX_MINIMUM_STACK ????
|
||||
#define TX_THREAD_USER_EXTENSION ????
|
||||
#define TX_TIMER_THREAD_STACK_SIZE ????
|
||||
#define TX_TIMER_THREAD_PRIORITY ????
|
||||
*/
|
||||
|
||||
/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls
|
||||
should be processed within the a system timer thread or directly in the timer ISR.
|
||||
By default, the timer thread is used. When the following is defined, the timer expiration
|
||||
processing is done directly from the timer ISR, thereby eliminating the timer thread control
|
||||
block, stack, and context switching to activate it. */
|
||||
|
||||
/*
|
||||
#define TX_TIMER_PROCESS_IN_ISR
|
||||
*/
|
||||
|
||||
/* Determine if in-line timer reactivation should be used within the timer expiration processing.
|
||||
By default, this is disabled and a function call is used. When the following is defined,
|
||||
reactivating is performed in-line resulting in faster timer processing but slightly larger
|
||||
code size. */
|
||||
|
||||
/*
|
||||
#define TX_REACTIVATE_INLINE
|
||||
*/
|
||||
|
||||
/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled,
|
||||
which places an 0xEF pattern in each byte of each thread's stack. This is used by
|
||||
debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */
|
||||
|
||||
/*
|
||||
#define TX_DISABLE_STACK_FILLING
|
||||
*/
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
/*
|
||||
#define TX_ENABLE_STACK_CHECKING
|
||||
*/
|
||||
|
||||
/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is
|
||||
enabled. If the application does not use preemption-threshold, it may be disabled to reduce
|
||||
code size and improve performance. */
|
||||
|
||||
/*
|
||||
#define TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
*/
|
||||
|
||||
/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears
|
||||
the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary
|
||||
clearing of ThreadX global variables. */
|
||||
|
||||
/*
|
||||
#define TX_DISABLE_REDUNDANT_CLEARING
|
||||
*/
|
||||
|
||||
/* Determine if no timer processing is required. This option will help eliminate the timer
|
||||
processing when not needed. The user will also have to comment out the call to
|
||||
tx_timer_interrupt, which is typically made from assembly language in
|
||||
tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR
|
||||
must also be used. */
|
||||
|
||||
/*
|
||||
#define TX_NO_TIMER
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
#define TX_TIMER_PROCESS_IN_ISR
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Determine if the notify callback option should be disabled. By default, notify callbacks are
|
||||
enabled. If the application does not use notify callbacks, they may be disabled to reduce
|
||||
code size and improve performance. */
|
||||
|
||||
/*
|
||||
#define TX_DISABLE_NOTIFY_CALLBACKS
|
||||
*/
|
||||
|
||||
|
||||
/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal
|
||||
code in-line. This results in a larger image, but improves the performance of the thread
|
||||
resume and suspend services. */
|
||||
|
||||
/*
|
||||
#define TX_INLINE_THREAD_RESUME_SUSPEND
|
||||
*/
|
||||
|
||||
|
||||
/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code
|
||||
size and less processing overhead, but increases the interrupt lockout time. */
|
||||
|
||||
/*
|
||||
#define TX_NOT_INTERRUPTABLE
|
||||
*/
|
||||
|
||||
|
||||
/* Determine if the trace event logging code should be enabled. This causes slight increases in
|
||||
code size and overhead, but provides the ability to generate system trace information which
|
||||
is available for viewing in TraceX. */
|
||||
|
||||
/*
|
||||
#define TX_ENABLE_EVENT_TRACE
|
||||
*/
|
||||
|
||||
|
||||
/* Determine if block pool performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various block pool performance information. */
|
||||
|
||||
/*
|
||||
#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if byte pool performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various byte pool performance information. */
|
||||
|
||||
/*
|
||||
#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if event flags performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various event flags performance information. */
|
||||
|
||||
/*
|
||||
#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if mutex performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various mutex performance information. */
|
||||
|
||||
/*
|
||||
#define TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if queue performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various queue performance information. */
|
||||
|
||||
/*
|
||||
#define TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if semaphore performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various semaphore performance information. */
|
||||
|
||||
/*
|
||||
#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if thread performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various thread performance information. */
|
||||
|
||||
/*
|
||||
#define TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
/* Determine if timer performance gathering is required by the application. When the following is
|
||||
defined, ThreadX gathers various timer performance information. */
|
||||
|
||||
/*
|
||||
#define TX_TIMER_ENABLE_PERFORMANCE_INFO
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
372
common/src/tx_block_allocate.c
Normal file
372
common/src/tx_block_allocate.c
Normal file
@ -0,0 +1,372 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
#include "tx_thread.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_allocate PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function allocates a block from the specified memory block */
|
||||
/* pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* block_ptr Pointer to place allocated block */
|
||||
/* pointer */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_suspend Suspend thread */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
TX_THREAD *thread_ptr;
|
||||
UCHAR *work_ptr;
|
||||
UCHAR *temp_ptr;
|
||||
UCHAR **next_block_ptr;
|
||||
UCHAR **return_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *entry_ptr;
|
||||
ULONG time_stamp = ((ULONG) 0);
|
||||
#endif
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
UCHAR *log_entry_ptr;
|
||||
ULONG upper_tbu;
|
||||
ULONG lower_tbu;
|
||||
#endif
|
||||
|
||||
|
||||
/* Disable interrupts to get a block from the pool. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total allocations counter. */
|
||||
_tx_block_pool_performance_allocate_count++;
|
||||
|
||||
/* Increment the number of allocations on this pool. */
|
||||
pool_ptr -> tx_block_pool_performance_allocate_count++;
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* If trace is enabled, save the current event pointer. */
|
||||
entry_ptr = _tx_trace_buffer_current_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_ALLOCATE, pool_ptr, 0, wait_option, pool_ptr -> tx_block_pool_available, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Save the time stamp for later comparison to verify that
|
||||
the event hasn't been overwritten by the time the allocate
|
||||
call succeeds. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
log_entry_ptr = *(UCHAR **) _tx_el_current_event;
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_ALLOCATE_INSERT
|
||||
|
||||
/* Store -1 in the third event slot. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) -1;
|
||||
|
||||
/* Save the time stamp for later comparison to verify that
|
||||
the event hasn't been overwritten by the time the allocate
|
||||
call succeeds. */
|
||||
lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET));
|
||||
upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET));
|
||||
#endif
|
||||
|
||||
/* Determine if there is an available block. */
|
||||
if (pool_ptr -> tx_block_pool_available != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Yes, a block is available. Decrement the available count. */
|
||||
pool_ptr -> tx_block_pool_available--;
|
||||
|
||||
/* Pickup the current block pointer. */
|
||||
work_ptr = pool_ptr -> tx_block_pool_available_list;
|
||||
|
||||
/* Return the first available block to the caller. */
|
||||
temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
|
||||
return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*return_ptr = temp_ptr;
|
||||
|
||||
/* Modify the available list to point at the next block in the pool. */
|
||||
next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
|
||||
pool_ptr -> tx_block_pool_available_list = *next_block_ptr;
|
||||
|
||||
/* Save the pool's address in the block for when it is released! */
|
||||
temp_ptr = TX_BLOCK_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
|
||||
*next_block_ptr = temp_ptr;
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the time stamp the same? */
|
||||
if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
|
||||
{
|
||||
|
||||
/* Timestamp is the same, update the entry with the address. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
|
||||
#else
|
||||
entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
/* Store the address of the allocated block. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr;
|
||||
#endif
|
||||
|
||||
/* Set status to success. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Default the return pointer to NULL. */
|
||||
return_ptr = TX_INDIRECT_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*return_ptr = TX_NULL;
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */
|
||||
status = TX_NO_MEMORY;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total suspensions counter. */
|
||||
_tx_block_pool_performance_suspension_count++;
|
||||
|
||||
/* Increment the number of suspensions on this pool. */
|
||||
pool_ptr -> tx_block_pool_performance_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_block_pool_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this pool control
|
||||
block. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr;
|
||||
|
||||
/* Save the return block pointer address as well. */
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) block_ptr;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Pickup the number of suspended threads. */
|
||||
suspended_count = (pool_ptr -> tx_block_pool_suspended_count);
|
||||
|
||||
/* Increment the number of suspended threads. */
|
||||
(pool_ptr -> tx_block_pool_suspended_count)++;
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = pool_ptr -> tx_block_pool_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_BLOCK_MEMORY;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the time-stamp the same? */
|
||||
if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
|
||||
{
|
||||
|
||||
/* Timestamp is the same, update the entry with the address. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
|
||||
#else
|
||||
entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*block_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
/* Check that the event time stamp is unchanged and the call is about
|
||||
to return success. A different timestamp means that a later event
|
||||
wrote over the block allocate event. A return value other than
|
||||
TX_SUCCESS indicates that no block was available. In those cases,
|
||||
do nothing here. */
|
||||
if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
|
||||
upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) &&
|
||||
((thread_ptr -> tx_thread_suspend_status) == TX_SUCCESS))
|
||||
{
|
||||
|
||||
/* Store the address of the allocated block. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) = (ULONG) *block_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_NO_MEMORY;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
213
common/src/tx_block_pool_cleanup.c
Normal file
213
common/src/tx_block_pool_cleanup.c
Normal file
@ -0,0 +1,213 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes block allocate timeout and thread terminate */
|
||||
/* actions that require the block pool data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_block_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_BLOCK_POOL *pool_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the block pool. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_block_pool_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to block pool control block. */
|
||||
pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for a NULL byte pool pointer. */
|
||||
if (pool_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Check for valid pool ID. */
|
||||
if (pool_ptr -> tx_block_pool_id == TX_BLOCK_POOL_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (pool_ptr -> tx_block_pool_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to block pool control block. */
|
||||
pool_ptr = TX_VOID_TO_BLOCK_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Yes, we still have thread suspension! */
|
||||
|
||||
/* Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Decrement the suspended count. */
|
||||
pool_ptr -> tx_block_pool_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = pool_ptr -> tx_block_pool_suspended_count;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (pool_ptr -> tx_block_pool_suspension_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_BLOCK_MEMORY)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread still suspended on the block pool.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_block_pool_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this block pool. */
|
||||
pool_ptr -> tx_block_pool_performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
213
common/src/tx_block_pool_create.c
Normal file
213
common/src/tx_block_pool_create.c
Normal file
@ -0,0 +1,213 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a pool of fixed-size memory blocks in the */
|
||||
/* specified memory area. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* name_ptr Pointer to block pool name */
|
||||
/* block_size Number of bytes in each block */
|
||||
/* pool_start Address of beginning of pool area */
|
||||
/* pool_size Number of bytes in the block pool */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size,
|
||||
VOID *pool_start, ULONG pool_size)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT blocks;
|
||||
UINT status;
|
||||
ULONG total_blocks;
|
||||
UCHAR *block_ptr;
|
||||
UCHAR **block_link_ptr;
|
||||
UCHAR *next_block_ptr;
|
||||
TX_BLOCK_POOL *next_pool;
|
||||
TX_BLOCK_POOL *previous_pool;
|
||||
|
||||
|
||||
/* Initialize block pool control block to all zeros. */
|
||||
TX_MEMSET(pool_ptr, 0, (sizeof(TX_BLOCK_POOL)));
|
||||
|
||||
/* Round the block size up to something that is evenly divisible by
|
||||
an ALIGN_TYPE (typically this is a 32-bit ULONG). This helps guarantee proper alignment. */
|
||||
block_size = (((block_size + (sizeof(ALIGN_TYPE))) - ((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
|
||||
|
||||
/* Round the pool size down to something that is evenly divisible by
|
||||
an ALIGN_TYPE (typically this is a 32-bit ULONG). */
|
||||
pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
|
||||
|
||||
/* Setup the basic block pool fields. */
|
||||
pool_ptr -> tx_block_pool_name = name_ptr;
|
||||
pool_ptr -> tx_block_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
pool_ptr -> tx_block_pool_size = pool_size;
|
||||
pool_ptr -> tx_block_pool_block_size = (UINT) block_size;
|
||||
|
||||
/* Calculate the total number of blocks. */
|
||||
total_blocks = pool_size/(block_size + (sizeof(UCHAR *)));
|
||||
|
||||
/* Walk through the pool area, setting up the available block list. */
|
||||
blocks = ((UINT) 0);
|
||||
block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
|
||||
while(blocks < (UINT) total_blocks)
|
||||
{
|
||||
|
||||
/* Yes, we have another block. Increment the block count. */
|
||||
blocks++;
|
||||
|
||||
/* Setup the link to the next block. */
|
||||
block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*block_link_ptr = next_block_ptr;
|
||||
|
||||
/* Advance to the next block. */
|
||||
block_ptr = next_block_ptr;
|
||||
|
||||
/* Update the next block pointer. */
|
||||
next_block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (block_size + (sizeof(UCHAR *))));
|
||||
}
|
||||
|
||||
/* Save the remaining information in the pool control block. */
|
||||
pool_ptr -> tx_block_pool_available = blocks;
|
||||
pool_ptr -> tx_block_pool_total = blocks;
|
||||
|
||||
/* Quickly check to make sure at least one block is in the pool. */
|
||||
if (blocks != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Backup to the last block in the pool. */
|
||||
block_ptr = TX_UCHAR_POINTER_SUB(block_ptr,(block_size + (sizeof(UCHAR *))));
|
||||
|
||||
/* Set the last block's forward pointer to NULL. */
|
||||
block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*block_link_ptr = TX_NULL;
|
||||
|
||||
/* Setup the starting pool address. */
|
||||
pool_ptr -> tx_block_pool_available_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
|
||||
/* Disable interrupts to place the block pool on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the block pool ID to make it valid. */
|
||||
pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID;
|
||||
|
||||
/* Place the block pool on the list of created block pools. First,
|
||||
check for an empty list. */
|
||||
if (_tx_block_pool_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created block pool list is empty. Add block pool to empty list. */
|
||||
_tx_block_pool_created_ptr = pool_ptr;
|
||||
pool_ptr -> tx_block_pool_created_next = pool_ptr;
|
||||
pool_ptr -> tx_block_pool_created_previous = pool_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_pool = _tx_block_pool_created_ptr;
|
||||
previous_pool = next_pool -> tx_block_pool_created_previous;
|
||||
|
||||
/* Place the new block pool in the list. */
|
||||
next_pool -> tx_block_pool_created_previous = pool_ptr;
|
||||
previous_pool -> tx_block_pool_created_next = pool_ptr;
|
||||
|
||||
/* Setup this block pool's created links. */
|
||||
pool_ptr -> tx_block_pool_created_previous = previous_pool;
|
||||
pool_ptr -> tx_block_pool_created_next = next_pool;
|
||||
}
|
||||
|
||||
/* Increment the created count. */
|
||||
_tx_block_pool_created_count++;
|
||||
|
||||
/* Optional block pool create extended processing. */
|
||||
TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BLOCK_POOL, pool_ptr, name_ptr, pool_size, block_size)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), blocks, block_size, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return successful status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enough memory for one block, return appropriate error. */
|
||||
status = TX_SIZE_ERROR;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
207
common/src/tx_block_pool_delete.c
Normal file
207
common/src/tx_block_pool_delete.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified block pool. All threads */
|
||||
/* suspended on the block pool are resumed with the TX_DELETED status */
|
||||
/* code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
UINT suspended_count;
|
||||
TX_BLOCK_POOL *next_pool;
|
||||
TX_BLOCK_POOL *previous_pool;
|
||||
|
||||
|
||||
/* Disable interrupts to remove the block pool from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_DELETE_INSERT
|
||||
|
||||
/* Optional block pool delete extended processing. */
|
||||
TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(pool_ptr)
|
||||
|
||||
/* Clear the block pool ID to make it invalid. */
|
||||
pool_ptr -> tx_block_pool_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of block pools. */
|
||||
_tx_block_pool_created_count--;
|
||||
|
||||
/* See if the block pool is the only one on the list. */
|
||||
if (_tx_block_pool_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created block pool, just set the created list to NULL. */
|
||||
_tx_block_pool_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_pool = pool_ptr -> tx_block_pool_created_next;
|
||||
previous_pool = pool_ptr -> tx_block_pool_created_previous;
|
||||
next_pool -> tx_block_pool_created_previous = previous_pool;
|
||||
previous_pool -> tx_block_pool_created_next = next_pool;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_block_pool_created_ptr == pool_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_block_pool_created_ptr = next_pool;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = pool_ptr -> tx_block_pool_suspension_list;
|
||||
pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
|
||||
suspended_count = pool_ptr -> tx_block_pool_suspended_count;
|
||||
pool_ptr -> tx_block_pool_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the block pool suspension list to resume any and all threads suspended
|
||||
on this block pool. */
|
||||
while (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_BLOCK_POOL_DELETE_PORT_COMPLETION(pool_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
146
common/src/tx_block_pool_info_get.c
Normal file
146
common/src/tx_block_pool_info_get.c
Normal file
@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified block pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to block pool control blk */
|
||||
/* name Destination for the pool name */
|
||||
/* available_blocks Number of free blocks in pool */
|
||||
/* total_blocks Total number of blocks in pool */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on block pool */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_pool Destination for pointer to next */
|
||||
/* block pool on the created list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks,
|
||||
ULONG *total_blocks, TX_THREAD **first_suspended,
|
||||
ULONG *suspended_count, TX_BLOCK_POOL **next_pool)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the block pool. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = pool_ptr -> tx_block_pool_name;
|
||||
}
|
||||
|
||||
/* Retrieve the number of available blocks in the block pool. */
|
||||
if (available_blocks != TX_NULL)
|
||||
{
|
||||
|
||||
*available_blocks = (ULONG) pool_ptr -> tx_block_pool_available;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of blocks in the block pool. */
|
||||
if (total_blocks != TX_NULL)
|
||||
{
|
||||
|
||||
*total_blocks = (ULONG) pool_ptr -> tx_block_pool_total;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this block pool. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = pool_ptr -> tx_block_pool_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this block pool. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) pool_ptr -> tx_block_pool_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next block pool created. */
|
||||
if (next_pool != TX_NULL)
|
||||
{
|
||||
|
||||
*next_pool = pool_ptr -> tx_block_pool_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
129
common/src/tx_block_pool_initialize.c
Normal file
129
common/src/tx_block_pool_initialize.c
Normal file
@ -0,0 +1,129 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Locate block pool component data in this file. */
|
||||
|
||||
/* Define the head pointer of the created block pool list. */
|
||||
|
||||
TX_BLOCK_POOL * _tx_block_pool_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created block pools. */
|
||||
|
||||
ULONG _tx_block_pool_created_count;
|
||||
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of block allocates. */
|
||||
|
||||
ULONG _tx_block_pool_performance_allocate_count;
|
||||
|
||||
|
||||
/* Define the total number of block releases. */
|
||||
|
||||
ULONG _tx_block_pool_performance_release_count;
|
||||
|
||||
|
||||
/* Define the total number of block pool suspensions. */
|
||||
|
||||
ULONG _tx_block_pool_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of block pool timeouts. */
|
||||
|
||||
ULONG _tx_block_pool_performance_timeout_count;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block pool_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the block pool component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_block_pool_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created block pools list and the
|
||||
number of block pools created. */
|
||||
_tx_block_pool_created_ptr = TX_NULL;
|
||||
_tx_block_pool_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize block pool performance counters. */
|
||||
_tx_block_pool_performance_allocate_count = ((ULONG) 0);
|
||||
_tx_block_pool_performance_release_count = ((ULONG) 0);
|
||||
_tx_block_pool_performance_suspension_count = ((ULONG) 0);
|
||||
_tx_block_pool_performance_timeout_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
201
common/src/tx_block_pool_performance_info_get.c
Normal file
201
common/src/tx_block_pool_performance_info_get.c
Normal file
@ -0,0 +1,201 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_block_pool.h"
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* block pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to block pool control blk */
|
||||
/* allocates Destination for the number of */
|
||||
/* allocations from this pool */
|
||||
/* releases Destination for the number of */
|
||||
/* blocks released back to pool */
|
||||
/* suspensions Destination for number of */
|
||||
/* suspensions on this pool */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this pool */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
|
||||
ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (pool_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Block pool pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the pool ID is invalid. */
|
||||
else if (pool_ptr -> tx_block_pool_id != TX_BLOCK_POOL_ID)
|
||||
{
|
||||
|
||||
/* Block pool pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of allocations from this block pool. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
*allocates = pool_ptr -> tx_block_pool_performance_allocate_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of blocks released to this block pool. */
|
||||
if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
*releases = pool_ptr -> tx_block_pool_performance_release_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of thread suspensions on this block pool. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = pool_ptr -> tx_block_pool_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of thread timeouts on this block pool. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = pool_ptr -> tx_block_pool_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return successful completion. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (pool_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
173
common/src/tx_block_pool_performance_system_info_get.c
Normal file
173
common/src/tx_block_pool_performance_system_info_get.c
Normal file
@ -0,0 +1,173 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_block_pool.h"
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves block pool performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* allocates Destination for the total number */
|
||||
/* of block allocations */
|
||||
/* releases Destination for the total number */
|
||||
/* of blocks released */
|
||||
/* suspensions Destination for the total number */
|
||||
/* of suspensions */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_performance_system_info_get(ULONG *allocates, ULONG *releases, ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of block allocations. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
*allocates = _tx_block_pool_performance_allocate_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of blocks released. */
|
||||
if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
*releases = _tx_block_pool_performance_release_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of block pool thread suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_block_pool_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of block pool thread timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_block_pool_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
249
common/src/tx_block_pool_prioritize.c
Normal file
249
common/src/tx_block_pool_prioritize.c
Normal file
@ -0,0 +1,249 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_pool_prioritize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places the highest priority suspended thread at the */
|
||||
/* front of the suspension list. All other threads remain in the same */
|
||||
/* FIFO suspension order. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *priority_thread_ptr;
|
||||
TX_THREAD *head_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT list_changed;
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = pool_ptr -> tx_block_pool_suspended_count;
|
||||
|
||||
/* Determine if there are fewer than 2 suspended threads. */
|
||||
if (suspended_count < ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if there how many threads are suspended on this block memory pool. */
|
||||
else if (suspended_count == ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Pickup the head pointer and the next pointer. */
|
||||
head_ptr = pool_ptr -> tx_block_pool_suspension_list;
|
||||
next_thread = head_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Determine if the next suspended thread has a higher priority. */
|
||||
if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
|
||||
{
|
||||
|
||||
/* Yes, move the list head to the next thread. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = next_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = pool_ptr -> tx_block_pool_suspension_list;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the list changed flag to false. */
|
||||
list_changed = TX_FALSE;
|
||||
|
||||
/* Search through the list to find the highest priority thread. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Is the current thread higher priority? */
|
||||
if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, remember that this thread is the highest priority. */
|
||||
priority_thread_ptr = thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if any changes to the list have occurred while
|
||||
interrupts were enabled. */
|
||||
|
||||
/* Is the list head the same? */
|
||||
if (head_ptr != pool_ptr -> tx_block_pool_suspension_list)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Is the suspended count the same? */
|
||||
if (suspended_count != pool_ptr -> tx_block_pool_suspended_count)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the list has changed. */
|
||||
if (list_changed == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Move the thread pointer to the next thread. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = pool_ptr -> tx_block_pool_suspension_list;
|
||||
suspended_count = pool_ptr -> tx_block_pool_suspended_count;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Reset the list changed flag. */
|
||||
list_changed = TX_FALSE;
|
||||
}
|
||||
|
||||
} while (thread_ptr != head_ptr);
|
||||
|
||||
/* Release preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Now determine if the highest priority thread is at the front
|
||||
of the list. */
|
||||
if (priority_thread_ptr != head_ptr)
|
||||
{
|
||||
|
||||
/* No, we need to move the highest priority suspended thread to the
|
||||
front of the list. */
|
||||
|
||||
/* First, remove the highest priority thread by updating the
|
||||
adjacent suspended threads. */
|
||||
next_thread = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Now, link the highest priority thread at the front of the list. */
|
||||
previous_thread = head_ptr -> tx_thread_suspended_previous;
|
||||
priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
|
||||
priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
|
||||
head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
|
||||
|
||||
/* Move the list head pointer to the highest priority suspended thread. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = priority_thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
/* Return successful status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
204
common/src/tx_block_release.c
Normal file
204
common/src/tx_block_release.c
Normal file
@ -0,0 +1,204 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Block Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_block_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_block_release PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns a previously allocated block to its */
|
||||
/* associated memory block pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* block_ptr Pointer to memory block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_block_release(VOID *block_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_BLOCK_POOL *pool_ptr;
|
||||
TX_THREAD *thread_ptr;
|
||||
UCHAR *work_ptr;
|
||||
UCHAR **return_block_ptr;
|
||||
UCHAR **next_block_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
/* Disable interrupts to put this block back in the pool. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Pickup the pool pointer which is just previous to the starting
|
||||
address of the block that the caller sees. */
|
||||
work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *)));
|
||||
next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
|
||||
pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT((*next_block_ptr));
|
||||
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total releases counter. */
|
||||
_tx_block_pool_performance_release_count++;
|
||||
|
||||
/* Increment the number of releases on this pool. */
|
||||
pool_ptr -> tx_block_pool_performance_release_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(block_ptr), pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&work_ptr), TX_TRACE_BLOCK_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BLOCK_RELEASE_INSERT
|
||||
|
||||
/* Determine if there are any threads suspended on the block pool. */
|
||||
thread_ptr = pool_ptr -> tx_block_pool_suspension_list;
|
||||
if (thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* Decrement the number of threads suspended. */
|
||||
(pool_ptr -> tx_block_pool_suspended_count)--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = (pool_ptr -> tx_block_pool_suspended_count);
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
pool_ptr -> tx_block_pool_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Return this block pointer to the suspended thread waiting for
|
||||
a block. */
|
||||
return_block_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*return_block_ptr = work_ptr;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No thread is suspended for a memory block. */
|
||||
|
||||
/* Put the block back in the available list. */
|
||||
*next_block_ptr = pool_ptr -> tx_block_pool_available_list;
|
||||
|
||||
/* Adjust the head pointer. */
|
||||
pool_ptr -> tx_block_pool_available_list = work_ptr;
|
||||
|
||||
/* Increment the count of available blocks. */
|
||||
pool_ptr -> tx_block_pool_available++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Return successful completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
409
common/src/tx_byte_allocate.c
Normal file
409
common/src/tx_byte_allocate.c
Normal file
@ -0,0 +1,409 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_allocate PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function allocates bytes from the specified memory byte */
|
||||
/* pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* memory_ptr Pointer to place allocated bytes */
|
||||
/* pointer */
|
||||
/* memory_size Number of bytes to allocate */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_suspend Suspend thread service */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* _tx_byte_pool_search Search byte pool for memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
TX_THREAD *thread_ptr;
|
||||
UCHAR *work_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT finished;
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
TX_TRACE_BUFFER_ENTRY *entry_ptr;
|
||||
ULONG time_stamp = ((ULONG) 0);
|
||||
#endif
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
UCHAR *log_entry_ptr;
|
||||
ULONG upper_tbu;
|
||||
ULONG lower_tbu;
|
||||
#endif
|
||||
|
||||
|
||||
/* Round the memory size up to the next size that is evenly divisible by
|
||||
an ALIGN_TYPE (this is typically a 32-bit ULONG). This guarantees proper alignment. */
|
||||
memory_size = (((memory_size + (sizeof(ALIGN_TYPE)))-((ALIGN_TYPE) 1))/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total allocations counter. */
|
||||
_tx_byte_pool_performance_allocate_count++;
|
||||
|
||||
/* Increment the number of allocations on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_allocate_count++;
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* If trace is enabled, save the current event pointer. */
|
||||
entry_ptr = _tx_trace_buffer_current_ptr;
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_ALLOCATE, pool_ptr, 0, memory_size, wait_option, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Save the time stamp for later comparison to verify that
|
||||
the event hasn't been overwritten by the time the allocate
|
||||
call succeeds. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
time_stamp = entry_ptr -> tx_trace_buffer_entry_time_stamp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
log_entry_ptr = *(UCHAR **) _tx_el_current_event;
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_ALLOCATE_INSERT
|
||||
|
||||
/* Store -1 in the fourth event slot. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) -1;
|
||||
|
||||
/* Save the time stamp for later comparison to verify that
|
||||
the event hasn't been overwritten by the time the allocate
|
||||
call succeeds. */
|
||||
lower_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET));
|
||||
upper_tbu = *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET));
|
||||
#endif
|
||||
|
||||
/* Set the search finished flag to false. */
|
||||
finished = TX_FALSE;
|
||||
|
||||
/* Loop to handle cases where the owner of the pool changed. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Indicate that this thread is the current owner. */
|
||||
pool_ptr -> tx_byte_pool_owner = thread_ptr;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* At this point, the executing thread owns the pool and can perform a search
|
||||
for free memory. */
|
||||
work_ptr = _tx_byte_pool_search(pool_ptr, memory_size);
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_BYTE_ALLOCATE_EXTENSION
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if we are finished. */
|
||||
if (work_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, we have found a block the search is finished. */
|
||||
finished = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No block was found, does this thread still own the pool? */
|
||||
if (pool_ptr -> tx_byte_pool_owner == thread_ptr)
|
||||
{
|
||||
|
||||
/* Yes, then we have looked through the entire pool and haven't found the memory. */
|
||||
finished = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
} while (finished == TX_FALSE);
|
||||
|
||||
/* Copy the pointer into the return destination. */
|
||||
*memory_ptr = (VOID *) work_ptr;
|
||||
|
||||
/* Determine if memory was found. */
|
||||
if (work_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the timestamp the same? */
|
||||
if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
|
||||
{
|
||||
|
||||
/* Timestamp is the same, update the entry with the address. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
|
||||
#else
|
||||
entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
|
||||
upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)))
|
||||
{
|
||||
/* Store the address of the allocated fragment. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Set the status to success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No memory of sufficient size was found... */
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_NO_MEMORY;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total suspensions counter. */
|
||||
_tx_byte_pool_performance_suspension_count++;
|
||||
|
||||
/* Increment the number of suspensions on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this pool control
|
||||
block. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr;
|
||||
|
||||
/* Save the return memory pointer address as well. */
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) memory_ptr;
|
||||
|
||||
/* Save the byte size requested. */
|
||||
thread_ptr -> tx_thread_suspend_info = memory_size;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Pickup the number of suspended threads. */
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
|
||||
/* Increment the suspension count. */
|
||||
(pool_ptr -> tx_byte_pool_suspended_count)++;
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_BYTE_MEMORY;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (entry_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the timestamp the same? */
|
||||
if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp)
|
||||
{
|
||||
|
||||
/* Timestamp is the same, update the entry with the address. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
entry_ptr -> tx_trace_buffer_entry_info_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
|
||||
#else
|
||||
entry_ptr -> tx_trace_buffer_entry_information_field_2 = TX_POINTER_TO_ULONG_CONVERT(*memory_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
/* Check that the event time stamp is unchanged. A different
|
||||
timestamp means that a later event wrote over the byte
|
||||
allocate event. In that case, do nothing here. */
|
||||
if (lower_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) &&
|
||||
upper_tbu == *((ULONG *) (log_entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)))
|
||||
{
|
||||
|
||||
/* Store the address of the allocated fragment. */
|
||||
*((ULONG *) (log_entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) = (ULONG) *memory_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
212
common/src/tx_byte_pool_cleanup.c
Normal file
212
common/src/tx_byte_pool_cleanup.c
Normal file
@ -0,0 +1,212 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes byte allocate timeout and thread terminate */
|
||||
/* actions that require the byte pool data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_byte_pool_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_BYTE_POOL *pool_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the byte pool. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_byte_pool_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to byte pool control block. */
|
||||
pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for a NULL byte pool pointer. */
|
||||
if (pool_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Check for valid pool ID. */
|
||||
if (pool_ptr -> tx_byte_pool_id == TX_BYTE_POOL_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to byte pool control block. */
|
||||
pool_ptr = TX_VOID_TO_BYTE_POOL_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Thread suspended for memory... Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
pool_ptr -> tx_byte_pool_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (pool_ptr -> tx_byte_pool_suspension_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_BYTE_MEMORY)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread still suspended on the byte pool.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_byte_pool_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this byte pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_NO_MEMORY;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
197
common/src/tx_byte_pool_create.c
Normal file
197
common/src/tx_byte_pool_create.c
Normal file
@ -0,0 +1,197 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a pool of memory bytes in the specified */
|
||||
/* memory area. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* name_ptr Pointer to byte pool name */
|
||||
/* pool_start Address of beginning of pool area */
|
||||
/* pool_size Number of bytes in the byte pool */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UCHAR *block_ptr;
|
||||
UCHAR **block_indirect_ptr;
|
||||
UCHAR *temp_ptr;
|
||||
TX_BYTE_POOL *next_pool;
|
||||
TX_BYTE_POOL *previous_pool;
|
||||
ALIGN_TYPE *free_ptr;
|
||||
|
||||
|
||||
/* Initialize the byte pool control block to all zeros. */
|
||||
TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL)));
|
||||
|
||||
/* Round the pool size down to something that is evenly divisible by
|
||||
an ULONG. */
|
||||
pool_size = (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
|
||||
|
||||
/* Setup the basic byte pool fields. */
|
||||
pool_ptr -> tx_byte_pool_name = name_ptr;
|
||||
|
||||
/* Save the start and size of the pool. */
|
||||
pool_ptr -> tx_byte_pool_start = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
pool_ptr -> tx_byte_pool_size = pool_size;
|
||||
|
||||
/* Setup memory list to the beginning as well as the search pointer. */
|
||||
pool_ptr -> tx_byte_pool_list = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
pool_ptr -> tx_byte_pool_search = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
|
||||
/* Initially, the pool will have two blocks. One large block at the
|
||||
beginning that is available and a small allocated block at the end
|
||||
of the pool that is there just for the algorithm. Be sure to count
|
||||
the available block's header in the available bytes count. */
|
||||
pool_ptr -> tx_byte_pool_available = pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
|
||||
pool_ptr -> tx_byte_pool_fragments = ((UINT) 2);
|
||||
|
||||
/* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE
|
||||
field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the
|
||||
owning pool (if the block is allocated). */
|
||||
|
||||
/* Calculate the end of the pool's memory area. */
|
||||
block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, pool_size);
|
||||
|
||||
/* Backup the end of the pool pointer and build the pre-allocated block. */
|
||||
block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
|
||||
|
||||
/* Cast the pool pointer into a ULONG. */
|
||||
temp_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
|
||||
block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*block_indirect_ptr = temp_ptr;
|
||||
|
||||
block_ptr = TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
|
||||
block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
|
||||
*block_indirect_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
|
||||
/* Now setup the large available block in the pool. */
|
||||
temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
block_indirect_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
|
||||
*block_indirect_ptr = block_ptr;
|
||||
block_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
|
||||
block_ptr = TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
|
||||
*free_ptr = TX_BYTE_BLOCK_FREE;
|
||||
|
||||
/* Clear the owner id. */
|
||||
pool_ptr -> tx_byte_pool_owner = TX_NULL;
|
||||
|
||||
/* Disable interrupts to place the byte pool on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the byte pool ID to make it valid. */
|
||||
pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID;
|
||||
|
||||
/* Place the byte pool on the list of created byte pools. First,
|
||||
check for an empty list. */
|
||||
if (_tx_byte_pool_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created byte pool list is empty. Add byte pool to empty list. */
|
||||
_tx_byte_pool_created_ptr = pool_ptr;
|
||||
pool_ptr -> tx_byte_pool_created_next = pool_ptr;
|
||||
pool_ptr -> tx_byte_pool_created_previous = pool_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_pool = _tx_byte_pool_created_ptr;
|
||||
previous_pool = next_pool -> tx_byte_pool_created_previous;
|
||||
|
||||
/* Place the new byte pool in the list. */
|
||||
next_pool -> tx_byte_pool_created_previous = pool_ptr;
|
||||
previous_pool -> tx_byte_pool_created_next = pool_ptr;
|
||||
|
||||
/* Setup this byte pool's created links. */
|
||||
pool_ptr -> tx_byte_pool_created_previous = previous_pool;
|
||||
pool_ptr -> tx_byte_pool_created_next = next_pool;
|
||||
}
|
||||
|
||||
/* Increment the number of created byte pools. */
|
||||
_tx_byte_pool_created_count++;
|
||||
|
||||
/* Optional byte pool create extended processing. */
|
||||
TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
211
common/src/tx_byte_pool_delete.c
Normal file
211
common/src/tx_byte_pool_delete.c
Normal file
@ -0,0 +1,211 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified byte pool. All threads */
|
||||
/* suspended on the byte pool are resumed with the TX_DELETED status */
|
||||
/* code. */
|
||||
/* */
|
||||
/* It is important to note that the byte pool being deleted, or the */
|
||||
/* memory associated with it should not be in use when this function */
|
||||
/* is called. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
UINT suspended_count;
|
||||
TX_BYTE_POOL *next_pool;
|
||||
TX_BYTE_POOL *previous_pool;
|
||||
|
||||
|
||||
/* Disable interrupts to remove the byte pool from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_DELETE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Optional byte pool delete extended processing. */
|
||||
TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(pool_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_DELETE_INSERT
|
||||
|
||||
/* Clear the byte pool ID to make it invalid. */
|
||||
pool_ptr -> tx_byte_pool_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of byte pools created. */
|
||||
_tx_byte_pool_created_count--;
|
||||
|
||||
/* See if the byte pool is the only one on the list. */
|
||||
if (_tx_byte_pool_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created byte pool, just set the created list to NULL. */
|
||||
_tx_byte_pool_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_pool = pool_ptr -> tx_byte_pool_created_next;
|
||||
previous_pool = pool_ptr -> tx_byte_pool_created_previous;
|
||||
next_pool -> tx_byte_pool_created_previous = previous_pool;
|
||||
previous_pool -> tx_byte_pool_created_next = next_pool;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_byte_pool_created_ptr == pool_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_byte_pool_created_ptr = next_pool;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
pool_ptr -> tx_byte_pool_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the byte pool list to resume any and all threads suspended
|
||||
on this byte pool. */
|
||||
while (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_BYTE_POOL_DELETE_PORT_COMPLETION(pool_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
146
common/src/tx_byte_pool_info_get.c
Normal file
146
common/src/tx_byte_pool_info_get.c
Normal file
@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified byte pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to byte pool control block*/
|
||||
/* name Destination for the pool name */
|
||||
/* available_bytes Number of free bytes in byte pool */
|
||||
/* fragments Number of fragments in byte pool */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on byte pool */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_pool Destination for pointer to next */
|
||||
/* byte pool on the created list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes,
|
||||
ULONG *fragments, TX_THREAD **first_suspended,
|
||||
ULONG *suspended_count, TX_BYTE_POOL **next_pool)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the byte pool. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = pool_ptr -> tx_byte_pool_name;
|
||||
}
|
||||
|
||||
/* Retrieve the number of available bytes in the byte pool. */
|
||||
if (available_bytes != TX_NULL)
|
||||
{
|
||||
|
||||
*available_bytes = pool_ptr -> tx_byte_pool_available;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of bytes in the byte pool. */
|
||||
if (fragments != TX_NULL)
|
||||
{
|
||||
|
||||
*fragments = (ULONG) pool_ptr -> tx_byte_pool_fragments;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this byte pool. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this byte pool. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) pool_ptr -> tx_byte_pool_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next byte pool created. */
|
||||
if (next_pool != TX_NULL)
|
||||
{
|
||||
|
||||
*next_pool = pool_ptr -> tx_byte_pool_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
147
common/src/tx_byte_pool_initialize.c
Normal file
147
common/src/tx_byte_pool_initialize.c
Normal file
@ -0,0 +1,147 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Locate byte pool component data in this file. */
|
||||
|
||||
/* Define the head pointer of the created byte pool list. */
|
||||
|
||||
TX_BYTE_POOL * _tx_byte_pool_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created byte pools. */
|
||||
|
||||
ULONG _tx_byte_pool_created_count;
|
||||
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of allocates. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_allocate_count;
|
||||
|
||||
|
||||
/* Define the total number of releases. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_release_count;
|
||||
|
||||
|
||||
/* Define the total number of adjacent memory fragment merges. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_merge_count;
|
||||
|
||||
|
||||
/* Define the total number of memory fragment splits. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_split_count;
|
||||
|
||||
|
||||
/* Define the total number of memory fragments searched during allocation. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_search_count;
|
||||
|
||||
|
||||
/* Define the total number of byte pool suspensions. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of byte pool timeouts. */
|
||||
|
||||
ULONG _tx_byte_pool_performance_timeout_count;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the byte pool component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_byte_pool_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created byte pools list and the
|
||||
number of byte pools created. */
|
||||
_tx_byte_pool_created_ptr = TX_NULL;
|
||||
_tx_byte_pool_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize byte pool performance counters. */
|
||||
_tx_byte_pool_performance_allocate_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_release_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_merge_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_split_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_search_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_suspension_count = ((ULONG) 0);
|
||||
_tx_byte_pool_performance_timeout_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
253
common/src/tx_byte_pool_performance_info_get.c
Normal file
253
common/src/tx_byte_pool_performance_info_get.c
Normal file
@ -0,0 +1,253 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_byte_pool.h"
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* byte pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to byte pool control block*/
|
||||
/* allocates Destination for number of */
|
||||
/* allocates on this pool */
|
||||
/* releases Destination for number of */
|
||||
/* releases on this pool */
|
||||
/* fragments_searched Destination for number of */
|
||||
/* fragments searched during */
|
||||
/* allocation */
|
||||
/* merges Destination for number of adjacent*/
|
||||
/* free fragments merged */
|
||||
/* splits Destination for number of */
|
||||
/* fragments split during */
|
||||
/* allocation */
|
||||
/* suspensions Destination for number of */
|
||||
/* suspensions on this pool */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this byte pool */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases,
|
||||
ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (pool_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Byte pool pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the pool ID is invalid. */
|
||||
else if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
|
||||
{
|
||||
|
||||
/* Byte pool pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PERFORMANCE_INFO_GET, pool_ptr, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of allocates on this byte pool. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
*allocates = pool_ptr -> tx_byte_pool_performance_allocate_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of releases on this byte pool. */
|
||||
if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
*releases = pool_ptr -> tx_byte_pool_performance_release_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of fragments searched in this byte pool. */
|
||||
if (fragments_searched != TX_NULL)
|
||||
{
|
||||
|
||||
*fragments_searched = pool_ptr -> tx_byte_pool_performance_search_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of fragments merged on this byte pool. */
|
||||
if (merges != TX_NULL)
|
||||
{
|
||||
|
||||
*merges = pool_ptr -> tx_byte_pool_performance_merge_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of fragment splits on this byte pool. */
|
||||
if (splits != TX_NULL)
|
||||
{
|
||||
|
||||
*splits = pool_ptr -> tx_byte_pool_performance_split_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of suspensions on this byte pool. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = pool_ptr -> tx_byte_pool_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of timeouts on this byte pool. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = pool_ptr -> tx_byte_pool_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (pool_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (fragments_searched != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (merges != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (splits != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
221
common/src/tx_byte_pool_performance_system_info_get.c
Normal file
221
common/src/tx_byte_pool_performance_system_info_get.c
Normal file
@ -0,0 +1,221 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_byte_pool.h"
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves byte pool performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* allocates Destination for total number of */
|
||||
/* allocates */
|
||||
/* releases Destination for total number of */
|
||||
/* releases */
|
||||
/* fragments_searched Destination for total number of */
|
||||
/* fragments searched during */
|
||||
/* allocation */
|
||||
/* merges Destination for total number of */
|
||||
/* adjacent free fragments merged */
|
||||
/* splits Destination for total number of */
|
||||
/* fragments split during */
|
||||
/* allocation */
|
||||
/* suspensions Destination for total number of */
|
||||
/* suspensions */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_performance_system_info_get(ULONG *allocates, ULONG *releases,
|
||||
ULONG *fragments_searched, ULONG *merges, ULONG *splits, ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of byte pool allocates. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
*allocates = _tx_byte_pool_performance_allocate_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool releases. */
|
||||
if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
*releases = _tx_byte_pool_performance_release_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool fragments searched. */
|
||||
if (fragments_searched != TX_NULL)
|
||||
{
|
||||
|
||||
*fragments_searched = _tx_byte_pool_performance_search_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool fragments merged. */
|
||||
if (merges != TX_NULL)
|
||||
{
|
||||
|
||||
*merges = _tx_byte_pool_performance_merge_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool fragment splits. */
|
||||
if (splits != TX_NULL)
|
||||
{
|
||||
|
||||
*splits = _tx_byte_pool_performance_split_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_byte_pool_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of byte pool timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_byte_pool_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (allocates != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (releases != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (fragments_searched != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (merges != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (splits != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
249
common/src/tx_byte_pool_prioritize.c
Normal file
249
common/src/tx_byte_pool_prioritize.c
Normal file
@ -0,0 +1,249 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_prioritize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places the highest priority suspended thread at the */
|
||||
/* front of the suspension list. All other threads remain in the same */
|
||||
/* FIFO suspension order. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *priority_thread_ptr;
|
||||
TX_THREAD *head_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT list_changed;
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_byte_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_POOL_PRIORITIZE_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
|
||||
/* Determine if there are fewer than 2 suspended threads. */
|
||||
if (suspended_count < ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if there how many threads are suspended on this byte memory pool. */
|
||||
else if (suspended_count == ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Pickup the head pointer and the next pointer. */
|
||||
head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
next_thread = head_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Determine if the next suspended thread has a higher priority. */
|
||||
if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
|
||||
{
|
||||
|
||||
/* Yes, move the list head to the next thread. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = next_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the list changed flag to false. */
|
||||
list_changed = TX_FALSE;
|
||||
|
||||
/* Search through the list to find the highest priority thread. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Is the current thread higher priority? */
|
||||
if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, remember that this thread is the highest priority. */
|
||||
priority_thread_ptr = thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if any changes to the list have occurred while
|
||||
interrupts were enabled. */
|
||||
|
||||
/* Is the list head the same? */
|
||||
if (head_ptr != pool_ptr -> tx_byte_pool_suspension_list)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Is the suspended count the same? */
|
||||
if (suspended_count != pool_ptr -> tx_byte_pool_suspended_count)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the list has changed. */
|
||||
if (list_changed == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Move the thread pointer to the next thread. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Reset the list changed flag. */
|
||||
list_changed = TX_FALSE;
|
||||
}
|
||||
|
||||
} while (thread_ptr != head_ptr);
|
||||
|
||||
/* Release preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Now determine if the highest priority thread is at the front
|
||||
of the list. */
|
||||
if (priority_thread_ptr != head_ptr)
|
||||
{
|
||||
|
||||
/* No, we need to move the highest priority suspended thread to the
|
||||
front of the list. */
|
||||
|
||||
/* First, remove the highest priority thread by updating the
|
||||
adjacent suspended threads. */
|
||||
next_thread = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Now, link the highest priority thread at the front of the list. */
|
||||
previous_thread = head_ptr -> tx_thread_suspended_previous;
|
||||
priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
|
||||
priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
|
||||
head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
|
||||
|
||||
/* Move the list head pointer to the highest priority suspended thread. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = priority_thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
350
common/src/tx_byte_pool_search.c
Normal file
350
common/src/tx_byte_pool_search.c
Normal file
@ -0,0 +1,350 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Pool */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_pool_search PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function searches a byte pool for a memory block to satisfy */
|
||||
/* the requested number of bytes. Merging of adjacent free blocks */
|
||||
/* takes place during the search and a split of the block that */
|
||||
/* satisfies the request may occur before this function returns. */
|
||||
/* */
|
||||
/* It is assumed that this function is called with interrupts enabled */
|
||||
/* and with the tx_pool_owner field set to the thread performing the */
|
||||
/* search. Also note that the search can occur during allocation and */
|
||||
/* release of a memory block. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* pool_ptr Pointer to pool control block */
|
||||
/* memory_size Number of bytes required */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* UCHAR * Pointer to the allocated memory, */
|
||||
/* if successful. Otherwise, a */
|
||||
/* NULL is returned */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_byte_allocate Allocate bytes of memory */
|
||||
/* _tx_byte_release Release bytes of memory */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UCHAR *_tx_byte_pool_search(TX_BYTE_POOL *pool_ptr, ULONG memory_size)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UCHAR *current_ptr;
|
||||
UCHAR *next_ptr;
|
||||
UCHAR **this_block_link_ptr;
|
||||
UCHAR **next_block_link_ptr;
|
||||
ULONG available_bytes;
|
||||
UINT examine_blocks;
|
||||
UINT first_free_block_found = TX_FALSE;
|
||||
TX_THREAD *thread_ptr;
|
||||
ALIGN_TYPE *free_ptr;
|
||||
UCHAR *work_ptr;
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* First, determine if there are enough bytes in the pool. */
|
||||
if (memory_size >= pool_ptr -> tx_byte_pool_available)
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Not enough memory, return a NULL pointer. */
|
||||
current_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup ownership of the byte pool. */
|
||||
pool_ptr -> tx_byte_pool_owner = thread_ptr;
|
||||
|
||||
/* Walk through the memory pool in search for a large enough block. */
|
||||
current_ptr = pool_ptr -> tx_byte_pool_search;
|
||||
examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1);
|
||||
available_bytes = ((ULONG) 0);
|
||||
do
|
||||
{
|
||||
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total fragment search counter. */
|
||||
_tx_byte_pool_performance_search_count++;
|
||||
|
||||
/* Increment the number of fragments searched on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_search_count++;
|
||||
#endif
|
||||
|
||||
/* Check to see if this block is free. */
|
||||
work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
|
||||
if ((*free_ptr) == TX_BYTE_BLOCK_FREE)
|
||||
{
|
||||
|
||||
/* Determine if this is the first free block. */
|
||||
if (first_free_block_found == TX_FALSE)
|
||||
{
|
||||
|
||||
/* This is the first free block. */
|
||||
pool_ptr->tx_byte_pool_search = current_ptr;
|
||||
|
||||
/* Set the flag to indicate we have found the first free
|
||||
block. */
|
||||
first_free_block_found = TX_TRUE;
|
||||
}
|
||||
|
||||
/* Block is free, see if it is large enough. */
|
||||
|
||||
/* Pickup the next block's pointer. */
|
||||
this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
|
||||
next_ptr = *this_block_link_ptr;
|
||||
|
||||
/* Calculate the number of bytes available in this block. */
|
||||
available_bytes = TX_UCHAR_POINTER_DIF(next_ptr, current_ptr);
|
||||
available_bytes = available_bytes - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)));
|
||||
|
||||
/* If this is large enough, we are done because our first-fit algorithm
|
||||
has been satisfied! */
|
||||
if (available_bytes >= memory_size)
|
||||
{
|
||||
/* Get out of the search loop! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Clear the available bytes variable. */
|
||||
available_bytes = ((ULONG) 0);
|
||||
|
||||
/* Not enough memory, check to see if the neighbor is
|
||||
free and can be merged. */
|
||||
work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
|
||||
if ((*free_ptr) == TX_BYTE_BLOCK_FREE)
|
||||
{
|
||||
|
||||
/* Yes, neighbor block can be merged! This is quickly accomplished
|
||||
by updating the current block with the next blocks pointer. */
|
||||
next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
|
||||
*this_block_link_ptr = *next_block_link_ptr;
|
||||
|
||||
/* Reduce the fragment total. We don't need to increase the bytes
|
||||
available because all free headers are also included in the available
|
||||
count. */
|
||||
pool_ptr -> tx_byte_pool_fragments--;
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total merge counter. */
|
||||
_tx_byte_pool_performance_merge_count++;
|
||||
|
||||
/* Increment the number of blocks merged on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_merge_count++;
|
||||
#endif
|
||||
|
||||
/* See if the search pointer is affected. */
|
||||
if (pool_ptr -> tx_byte_pool_search == next_ptr)
|
||||
{
|
||||
|
||||
/* Yes, update the search pointer. */
|
||||
pool_ptr -> tx_byte_pool_search = current_ptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Neighbor is not free so we can skip over it! */
|
||||
next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
|
||||
current_ptr = *next_block_link_ptr;
|
||||
|
||||
/* Decrement the examined block count to account for this one. */
|
||||
if (examine_blocks != ((UINT) 0))
|
||||
{
|
||||
|
||||
examine_blocks--;
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total fragment search counter. */
|
||||
_tx_byte_pool_performance_search_count++;
|
||||
|
||||
/* Increment the number of fragments searched on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_search_count++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Block is not free, move to next block. */
|
||||
this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
|
||||
current_ptr = *this_block_link_ptr;
|
||||
}
|
||||
|
||||
/* Another block has been searched... decrement counter. */
|
||||
if (examine_blocks != ((UINT) 0))
|
||||
{
|
||||
|
||||
examine_blocks--;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if anything has changed in terms of pool ownership. */
|
||||
if (pool_ptr -> tx_byte_pool_owner != thread_ptr)
|
||||
{
|
||||
|
||||
/* Pool changed ownership in the brief period interrupts were
|
||||
enabled. Reset the search. */
|
||||
current_ptr = pool_ptr -> tx_byte_pool_search;
|
||||
examine_blocks = pool_ptr -> tx_byte_pool_fragments + ((UINT) 1);
|
||||
|
||||
/* Setup our ownership again. */
|
||||
pool_ptr -> tx_byte_pool_owner = thread_ptr;
|
||||
}
|
||||
} while(examine_blocks != ((UINT) 0));
|
||||
|
||||
/* Determine if a block was found. If so, determine if it needs to be
|
||||
split. */
|
||||
if (available_bytes != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Determine if we need to split this block. */
|
||||
if ((available_bytes - memory_size) >= ((ULONG) TX_BYTE_BLOCK_MIN))
|
||||
{
|
||||
|
||||
/* Split the block. */
|
||||
next_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (memory_size + ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
|
||||
|
||||
/* Setup the new free block. */
|
||||
next_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
|
||||
this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
|
||||
*next_block_link_ptr = *this_block_link_ptr;
|
||||
work_ptr = TX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
|
||||
*free_ptr = TX_BYTE_BLOCK_FREE;
|
||||
|
||||
/* Increase the total fragment counter. */
|
||||
pool_ptr -> tx_byte_pool_fragments++;
|
||||
|
||||
/* Update the current pointer to point at the newly created block. */
|
||||
*this_block_link_ptr = next_ptr;
|
||||
|
||||
/* Set available equal to memory size for subsequent calculation. */
|
||||
available_bytes = memory_size;
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total split counter. */
|
||||
_tx_byte_pool_performance_split_count++;
|
||||
|
||||
/* Increment the number of blocks split on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_split_count++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* In any case, mark the current block as allocated. */
|
||||
work_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *)));
|
||||
this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
|
||||
*this_block_link_ptr = TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
|
||||
|
||||
/* Reduce the number of available bytes in the pool. */
|
||||
pool_ptr -> tx_byte_pool_available = (pool_ptr -> tx_byte_pool_available - available_bytes) - ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)));
|
||||
|
||||
/* Determine if the search pointer needs to be updated. This is only done
|
||||
if the search pointer matches the block to be returned. */
|
||||
if (current_ptr == pool_ptr -> tx_byte_pool_search)
|
||||
{
|
||||
|
||||
/* Yes, update the search pointer to the next block. */
|
||||
this_block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
|
||||
pool_ptr -> tx_byte_pool_search = *this_block_link_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Adjust the pointer for the application. */
|
||||
current_ptr = TX_UCHAR_POINTER_ADD(current_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Set current pointer to NULL to indicate nothing was found. */
|
||||
current_ptr = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the search pointer. */
|
||||
return(current_ptr);
|
||||
}
|
||||
|
376
common/src/tx_byte_release.c
Normal file
376
common/src/tx_byte_release.c
Normal file
@ -0,0 +1,376 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Byte Memory */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_byte_release PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns previously allocated memory to its */
|
||||
/* associated memory byte pool. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* memory_ptr Pointer to allocated memory */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* [TX_PTR_ERROR | TX_SUCCESS] Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_byte_pool_search Search the byte pool for memory */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_byte_release(VOID *memory_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
TX_BYTE_POOL *pool_ptr;
|
||||
TX_THREAD *thread_ptr;
|
||||
UCHAR *work_ptr;
|
||||
UCHAR *temp_ptr;
|
||||
UCHAR *next_block_ptr;
|
||||
TX_THREAD *susp_thread_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
ULONG memory_size;
|
||||
ALIGN_TYPE *free_ptr;
|
||||
TX_BYTE_POOL **byte_pool_ptr;
|
||||
UCHAR **block_link_ptr;
|
||||
UCHAR **suspend_info_ptr;
|
||||
|
||||
|
||||
/* Default to successful status. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Set the pool pointer to NULL. */
|
||||
pool_ptr = TX_NULL;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the memory pointer is valid. */
|
||||
work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(memory_ptr);
|
||||
if (work_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Back off the memory pointer to pickup its header. */
|
||||
work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, ((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE))));
|
||||
|
||||
/* There is a pointer, pickup the pool pointer address. */
|
||||
temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
|
||||
if ((*free_ptr) != TX_BYTE_BLOCK_FREE)
|
||||
{
|
||||
|
||||
/* Pickup the pool pointer. */
|
||||
temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
|
||||
byte_pool_ptr = TX_UCHAR_TO_INDIRECT_BYTE_POOL_POINTER(temp_ptr);
|
||||
pool_ptr = *byte_pool_ptr;
|
||||
|
||||
/* See if we have a valid pool pointer. */
|
||||
if (pool_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Return pointer error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* See if we have a valid pool. */
|
||||
if (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID)
|
||||
{
|
||||
|
||||
/* Return pointer error. */
|
||||
status = TX_PTR_ERROR;
|
||||
|
||||
/* Reset the pool pointer is NULL. */
|
||||
pool_ptr = TX_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Return pointer error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Return pointer error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the pointer is valid. */
|
||||
if (pool_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At this point, we know that the pointer is valid. */
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Indicate that this thread is the current owner. */
|
||||
pool_ptr -> tx_byte_pool_owner = thread_ptr;
|
||||
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total release counter. */
|
||||
_tx_byte_pool_performance_release_count++;
|
||||
|
||||
/* Increment the number of releases on this pool. */
|
||||
pool_ptr -> tx_byte_pool_performance_release_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(memory_ptr), pool_ptr -> tx_byte_pool_suspended_count, pool_ptr -> tx_byte_pool_available, TX_TRACE_BYTE_POOL_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_BYTE_RELEASE_INSERT
|
||||
|
||||
/* Release the memory. */
|
||||
temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
|
||||
*free_ptr = TX_BYTE_BLOCK_FREE;
|
||||
|
||||
/* Update the number of available bytes in the pool. */
|
||||
block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
|
||||
next_block_ptr = *block_link_ptr;
|
||||
pool_ptr -> tx_byte_pool_available =
|
||||
pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr);
|
||||
|
||||
/* Determine if the free block is prior to current search pointer. */
|
||||
if (work_ptr < (pool_ptr -> tx_byte_pool_search))
|
||||
{
|
||||
|
||||
/* Yes, update the search pointer to the released block. */
|
||||
pool_ptr -> tx_byte_pool_search = work_ptr;
|
||||
}
|
||||
|
||||
/* Determine if there are threads suspended on this byte pool. */
|
||||
if (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Now examine the suspension list to find threads waiting for
|
||||
memory. Maybe it is now available! */
|
||||
while (pool_ptr -> tx_byte_pool_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Pickup the first suspended thread pointer. */
|
||||
susp_thread_ptr = pool_ptr -> tx_byte_pool_suspension_list;
|
||||
|
||||
/* Pickup the size of the memory the thread is requesting. */
|
||||
memory_size = susp_thread_ptr -> tx_thread_suspend_info;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* See if the request can be satisfied. */
|
||||
work_ptr = _tx_byte_pool_search(pool_ptr, memory_size);
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_BYTE_RELEASE_EXTENSION
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Indicate that this thread is the current owner. */
|
||||
pool_ptr -> tx_byte_pool_owner = thread_ptr;
|
||||
|
||||
/* If there is not enough memory, break this loop! */
|
||||
if (work_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Break out of the loop. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check to make sure the thread is still suspended. */
|
||||
if (susp_thread_ptr == pool_ptr -> tx_byte_pool_suspension_list)
|
||||
{
|
||||
|
||||
/* Also, makes sure the memory size is the same. */
|
||||
if (susp_thread_ptr -> tx_thread_suspend_info == memory_size)
|
||||
{
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* Decrement the number of threads suspended. */
|
||||
pool_ptr -> tx_byte_pool_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
pool_ptr -> tx_byte_pool_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = susp_thread_ptr -> tx_thread_suspended_next;
|
||||
pool_ptr -> tx_byte_pool_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = susp_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Prepare for resumption of the thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
susp_thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Return this block pointer to the suspended thread waiting for
|
||||
a block. */
|
||||
suspend_info_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(susp_thread_ptr -> tx_thread_additional_suspend_info);
|
||||
*suspend_info_ptr = work_ptr;
|
||||
|
||||
/* Clear the memory pointer to indicate that it was given to the suspended thread. */
|
||||
work_ptr = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
susp_thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(susp_thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(susp_thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the memory was given to the suspended thread. */
|
||||
if (work_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* No, it wasn't given to the suspended thread. */
|
||||
|
||||
/* Put the memory back on the available list since this thread is no longer
|
||||
suspended. */
|
||||
work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (((sizeof(UCHAR *)) + (sizeof(ALIGN_TYPE)))));
|
||||
temp_ptr = TX_UCHAR_POINTER_ADD(work_ptr, (sizeof(UCHAR *)));
|
||||
free_ptr = TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(temp_ptr);
|
||||
*free_ptr = TX_BYTE_BLOCK_FREE;
|
||||
|
||||
/* Update the number of available bytes in the pool. */
|
||||
block_link_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
|
||||
next_block_ptr = *block_link_ptr;
|
||||
pool_ptr -> tx_byte_pool_available =
|
||||
pool_ptr -> tx_byte_pool_available + TX_UCHAR_POINTER_DIF(next_block_ptr, work_ptr);
|
||||
|
||||
/* Determine if the current pointer is before the search pointer. */
|
||||
if (work_ptr < (pool_ptr -> tx_byte_pool_search))
|
||||
{
|
||||
|
||||
/* Yes, update the search pointer. */
|
||||
pool_ptr -> tx_byte_pool_search = work_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, threads suspended, restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
237
common/src/tx_event_flags_cleanup.c
Normal file
237
common/src/tx_event_flags_cleanup.c
Normal file
@ -0,0 +1,237 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes event flags timeout and thread terminate */
|
||||
/* actions that require the event flags data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_EVENT_FLAGS_GROUP *group_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *suspension_head;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the event flags group. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_event_flags_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to event flags control block. */
|
||||
group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for a NULL event flags control block pointer. */
|
||||
if (group_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the group pointer ID valid? */
|
||||
if (group_ptr -> tx_event_flags_group_id == TX_EVENT_FLAGS_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to event flags control block. */
|
||||
group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Yes, we still have thread suspension! */
|
||||
|
||||
/* Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||||
|
||||
/* Pickup the suspension head. */
|
||||
suspension_head = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
|
||||
/* Determine if the cleanup is being done while a set operation was interrupted. If the
|
||||
suspended count is non-zero and the suspension head is NULL, the list is being processed
|
||||
and cannot be touched from here. The suspension list removal will instead take place
|
||||
inside the event flag set code. */
|
||||
if (suspension_head != TX_NULL)
|
||||
{
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* Decrement the local suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Store the updated suspended count. */
|
||||
group_ptr -> tx_event_flags_group_suspended_count = suspended_count;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (suspension_head == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* In this case, the search pointer in an interrupted event flag set must be reset. */
|
||||
group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread still suspended on the event flags group.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_event_flags_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this event flags group. */
|
||||
group_ptr -> tx_event_flags_group____performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_NO_EVENTS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! Check for preemption even though we are executing
|
||||
from the system timer thread right now which normally executes at the
|
||||
highest priority. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
141
common/src/tx_event_flags_create.c
Normal file
141
common/src/tx_event_flags_create.c
Normal file
@ -0,0 +1,141 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a group of 32 event flags. All the flags are */
|
||||
/* initially in a cleared state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to event flags group */
|
||||
/* control block */
|
||||
/* name_ptr Pointer to event flags name */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_EVENT_FLAGS_GROUP *next_group;
|
||||
TX_EVENT_FLAGS_GROUP *previous_group;
|
||||
|
||||
|
||||
/* Initialize event flags control block to all zeros. */
|
||||
TX_MEMSET(group_ptr, 0, (sizeof(TX_EVENT_FLAGS_GROUP)));
|
||||
|
||||
/* Setup the basic event flags group fields. */
|
||||
group_ptr -> tx_event_flags_group_name = name_ptr;
|
||||
|
||||
/* Disable interrupts to put the event flags group on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the event flags ID to make it valid. */
|
||||
group_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID;
|
||||
|
||||
/* Place the group on the list of created event flag groups. First,
|
||||
check for an empty list. */
|
||||
if (_tx_event_flags_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created event flags list is empty. Add event flag group to empty list. */
|
||||
_tx_event_flags_created_ptr = group_ptr;
|
||||
group_ptr -> tx_event_flags_group_created_next = group_ptr;
|
||||
group_ptr -> tx_event_flags_group_created_previous = group_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_group = _tx_event_flags_created_ptr;
|
||||
previous_group = next_group -> tx_event_flags_group_created_previous;
|
||||
|
||||
/* Place the new event flag group in the list. */
|
||||
next_group -> tx_event_flags_group_created_previous = group_ptr;
|
||||
previous_group -> tx_event_flags_group_created_next = group_ptr;
|
||||
|
||||
/* Setup this group's created links. */
|
||||
group_ptr -> tx_event_flags_group_created_previous = previous_group;
|
||||
group_ptr -> tx_event_flags_group_created_next = next_group;
|
||||
}
|
||||
|
||||
/* Increment the number of created event flag groups. */
|
||||
_tx_event_flags_created_count++;
|
||||
|
||||
/* Optional event flag group create extended processing. */
|
||||
TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_EVENT_FLAGS, group_ptr, name_ptr, 0, 0)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_CREATE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_group), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
207
common/src/tx_event_flags_delete.c
Normal file
207
common/src/tx_event_flags_delete.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified event flag group. All threads */
|
||||
/* suspended on the group are resumed with the TX_DELETED status */
|
||||
/* code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to group control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
UINT suspended_count;
|
||||
TX_EVENT_FLAGS_GROUP *next_group;
|
||||
TX_EVENT_FLAGS_GROUP *previous_group;
|
||||
|
||||
|
||||
/* Disable interrupts to remove the group from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_DELETE, group_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Optional event flags group delete extended processing. */
|
||||
TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(group_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_DELETE_INSERT
|
||||
|
||||
/* Clear the event flag group ID to make it invalid. */
|
||||
group_ptr -> tx_event_flags_group_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of created event flag groups. */
|
||||
_tx_event_flags_created_count--;
|
||||
|
||||
/* See if this group is the only one on the list. */
|
||||
if (_tx_event_flags_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created event flag group, just set the created list to NULL. */
|
||||
_tx_event_flags_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_group = group_ptr -> tx_event_flags_group_created_next;
|
||||
previous_group = group_ptr -> tx_event_flags_group_created_previous;
|
||||
next_group -> tx_event_flags_group_created_previous = previous_group;
|
||||
previous_group -> tx_event_flags_group_created_next = next_group;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_event_flags_created_ptr == group_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_event_flags_created_ptr = next_group;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||||
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||||
group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the event flag suspension list to resume any and all threads
|
||||
suspended on this group. */
|
||||
while (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Decrement the number of suspended threads. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_EVENT_FLAGS_GROUP_DELETE_PORT_COMPLETION(group_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
401
common/src/tx_event_flags_get.c
Normal file
401
common/src/tx_event_flags_get.c
Normal file
@ -0,0 +1,401 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the specified event flags from the group, */
|
||||
/* according to the get option. The get option also specifies whether */
|
||||
/* or not the retrieved flags are cleared. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to group control block */
|
||||
/* requested_event_flags Event flags requested */
|
||||
/* get_option Specifies and/or and clear options*/
|
||||
/* actual_flags_ptr Pointer to place the actual flags */
|
||||
/* the service retrieved */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_suspend Suspend thread service */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags,
|
||||
UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT status;
|
||||
UINT and_request;
|
||||
UINT clear_request;
|
||||
ULONG current_flags;
|
||||
ULONG flags_satisfied;
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
ULONG delayed_clear_flags;
|
||||
#endif
|
||||
UINT suspended_count;
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
UINT interrupted_set_request;
|
||||
#endif
|
||||
|
||||
|
||||
/* Disable interrupts to examine the event flags group. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total event flags get counter. */
|
||||
_tx_event_flags_performance_get_count++;
|
||||
|
||||
/* Increment the number of event flags gets on this semaphore. */
|
||||
group_ptr -> tx_event_flags_group__performance_get_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_GET, group_ptr, requested_flags, group_ptr -> tx_event_flags_group_current, get_option, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_GET_INSERT
|
||||
|
||||
/* Pickup current flags. */
|
||||
current_flags = group_ptr -> tx_event_flags_group_current;
|
||||
|
||||
/* Apply the event flag option mask. */
|
||||
and_request = (get_option & TX_AND);
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Check for AND condition. All flags must be present to satisfy request. */
|
||||
if (and_request == TX_AND)
|
||||
{
|
||||
|
||||
/* AND request is present. */
|
||||
|
||||
/* Calculate the flags present. */
|
||||
flags_satisfied = (current_flags & requested_flags);
|
||||
|
||||
/* Determine if they satisfy the AND request. */
|
||||
if (flags_satisfied != requested_flags)
|
||||
{
|
||||
|
||||
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||||
flags_satisfied = ((ULONG) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* OR request is present. Simply or the requested flags and the current flags. */
|
||||
flags_satisfied = (current_flags & requested_flags);
|
||||
}
|
||||
|
||||
/* Determine if the request is satisfied. */
|
||||
if (flags_satisfied != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Return the actual event flags that satisfied the request. */
|
||||
*actual_flags_ptr = current_flags;
|
||||
|
||||
/* Pickup the clear bit. */
|
||||
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||||
|
||||
/* Determine whether or not clearing needs to take place. */
|
||||
if (clear_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, clear the flags that satisfied this request. */
|
||||
group_ptr -> tx_event_flags_group_current =
|
||||
group_ptr -> tx_event_flags_group_current & (~requested_flags);
|
||||
}
|
||||
|
||||
/* Return success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Pickup delayed clear flags. */
|
||||
delayed_clear_flags = group_ptr -> tx_event_flags_group_delayed_clear;
|
||||
|
||||
/* Determine if there are any delayed clear operations pending. */
|
||||
if (delayed_clear_flags != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Yes, apply them to the current flags. */
|
||||
current_flags = current_flags & (~delayed_clear_flags);
|
||||
}
|
||||
|
||||
/* Check for AND condition. All flags must be present to satisfy request. */
|
||||
if (and_request == TX_AND)
|
||||
{
|
||||
|
||||
/* AND request is present. */
|
||||
|
||||
/* Calculate the flags present. */
|
||||
flags_satisfied = (current_flags & requested_flags);
|
||||
|
||||
/* Determine if they satisfy the AND request. */
|
||||
if (flags_satisfied != requested_flags)
|
||||
{
|
||||
|
||||
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||||
flags_satisfied = ((ULONG) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* OR request is present. Simply AND together the requested flags and the current flags
|
||||
to see if any are present. */
|
||||
flags_satisfied = (current_flags & requested_flags);
|
||||
}
|
||||
|
||||
/* Determine if the request is satisfied. */
|
||||
if (flags_satisfied != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Yes, this request can be handled immediately. */
|
||||
|
||||
/* Return the actual event flags that satisfied the request. */
|
||||
*actual_flags_ptr = current_flags;
|
||||
|
||||
/* Pickup the clear bit. */
|
||||
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||||
|
||||
/* Determine whether or not clearing needs to take place. */
|
||||
if (clear_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Set interrupted set request flag to false. */
|
||||
interrupted_set_request = TX_FALSE;
|
||||
|
||||
/* Determine if the suspension list is being processed by an interrupted
|
||||
set request. */
|
||||
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL)
|
||||
{
|
||||
|
||||
/* Set the interrupted set request flag. */
|
||||
interrupted_set_request = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Was a set request interrupted? */
|
||||
if (interrupted_set_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* A previous set operation is was interrupted, we need to defer the
|
||||
event clearing until the set operation is complete. */
|
||||
|
||||
/* Remember the events to clear. */
|
||||
group_ptr -> tx_event_flags_group_delayed_clear =
|
||||
group_ptr -> tx_event_flags_group_delayed_clear | requested_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Yes, clear the flags that satisfied this request. */
|
||||
group_ptr -> tx_event_flags_group_current =
|
||||
group_ptr -> tx_event_flags_group_current & ~requested_flags;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set status to success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
else
|
||||
{
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point, return error completion. */
|
||||
status = TX_NO_EVENTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total event flags suspensions counter. */
|
||||
_tx_event_flags_performance_suspension_count++;
|
||||
|
||||
/* Increment the number of event flags suspensions on this semaphore. */
|
||||
group_ptr -> tx_event_flags_group___performance_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_event_flags_cleanup);
|
||||
|
||||
/* Remember which event flags we are looking for. */
|
||||
thread_ptr -> tx_thread_suspend_info = requested_flags;
|
||||
|
||||
/* Save the get option as well. */
|
||||
thread_ptr -> tx_thread_suspend_option = get_option;
|
||||
|
||||
/* Save the destination for the current events. */
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) actual_flags_ptr;
|
||||
|
||||
/* Setup cleanup information, i.e. this event flags group control
|
||||
block. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) group_ptr;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the number of threads suspended. */
|
||||
group_ptr -> tx_event_flags_group_suspended_count++;
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_EVENT_FLAG;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_NO_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
143
common/src/tx_event_flags_info_get.c
Normal file
143
common/src/tx_event_flags_info_get.c
Normal file
@ -0,0 +1,143 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified event flag */
|
||||
/* group. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to event flag group */
|
||||
/* name Destination for the event flag */
|
||||
/* group name */
|
||||
/* current_flags Current event flags */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on event flags */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_group Destination for pointer to next */
|
||||
/* event flag group on the created */
|
||||
/* list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags,
|
||||
TX_THREAD **first_suspended, ULONG *suspended_count,
|
||||
TX_EVENT_FLAGS_GROUP **next_group)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the event flag group. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = group_ptr -> tx_event_flags_group_name;
|
||||
}
|
||||
|
||||
/* Retrieve the current event flags in the event flag group. */
|
||||
if (current_flags != TX_NULL)
|
||||
{
|
||||
|
||||
/* Pickup the current flags and apply delayed clearing. */
|
||||
*current_flags = group_ptr -> tx_event_flags_group_current &
|
||||
~group_ptr -> tx_event_flags_group_delayed_clear;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this event flag group. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this event flag group. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) group_ptr -> tx_event_flags_group_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next event flag group created. */
|
||||
if (next_group != TX_NULL)
|
||||
{
|
||||
|
||||
*next_group = group_ptr -> tx_event_flags_group_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
130
common/src/tx_event_flags_initialize.c
Normal file
130
common/src/tx_event_flags_initialize.c
Normal file
@ -0,0 +1,130 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Locate event flags component data in this file. */
|
||||
/* Define the head pointer of the created event flags list. */
|
||||
|
||||
TX_EVENT_FLAGS_GROUP * _tx_event_flags_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created event flag groups. */
|
||||
|
||||
ULONG _tx_event_flags_created_count;
|
||||
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of event flag sets. */
|
||||
|
||||
ULONG _tx_event_flags_performance_set_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag gets. */
|
||||
|
||||
ULONG _tx_event_flags_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag suspensions. */
|
||||
|
||||
ULONG _tx_event_flags_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of event flag timeouts. */
|
||||
|
||||
ULONG _tx_event_flags_performance_timeout_count;
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the event flags component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_event_flags_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created event flags list and the
|
||||
number of event flags created. */
|
||||
_tx_event_flags_created_ptr = TX_NULL;
|
||||
_tx_event_flags_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize event flags performance counters. */
|
||||
_tx_event_flags_performance_set_count = ((ULONG) 0);
|
||||
_tx_event_flags_performance_get_count = ((ULONG) 0);
|
||||
_tx_event_flags_performance_suspension_count = ((ULONG) 0);
|
||||
_tx_event_flags_performance_timeout_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
202
common/src/tx_event_flags_performance_info_get.c
Normal file
202
common/src/tx_event_flags_performance_info_get.c
Normal file
@ -0,0 +1,202 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_event_flags.h"
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* event flag group. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to event flag group */
|
||||
/* sets Destination for the number of */
|
||||
/* event flag sets on this group */
|
||||
/* gets Destination for the number of */
|
||||
/* event flag gets on this group */
|
||||
/* suspensions Destination for the number of */
|
||||
/* event flag suspensions on this */
|
||||
/* group */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this event flag group */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets,
|
||||
ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (group_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Event flags group pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the event group ID is invalid. */
|
||||
else if (group_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)
|
||||
{
|
||||
|
||||
/* Event flags group pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_PERFORMANCE_INFO_GET, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of set operations on this event flag group. */
|
||||
if (sets != TX_NULL)
|
||||
{
|
||||
|
||||
*sets = group_ptr -> tx_event_flags_group_performance_set_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of get operations on this event flag group. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = group_ptr -> tx_event_flags_group__performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of thread suspensions on this event flag group. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = group_ptr -> tx_event_flags_group___performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of thread timeouts on this event flag group. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = group_ptr -> tx_event_flags_group____performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return successful completion. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (group_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (sets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
174
common/src/tx_event_flags_performance_system_info_get.c
Normal file
174
common/src/tx_event_flags_performance_system_info_get.c
Normal file
@ -0,0 +1,174 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_event_flags.h"
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves system event flag performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* sets Destination for total number of */
|
||||
/* event flag sets */
|
||||
/* gets Destination for total number of */
|
||||
/* event flag gets */
|
||||
/* suspensions Destination for total number of */
|
||||
/* event flag suspensions */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_performance_system_info_get(ULONG *sets, ULONG *gets, ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS__PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of event flag set operations. */
|
||||
if (sets != TX_NULL)
|
||||
{
|
||||
|
||||
*sets = _tx_event_flags_performance_set_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of event flag get operations. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = _tx_event_flags_performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of event flag thread suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_event_flags_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of event flag thread timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_event_flags_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (sets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
620
common/src/tx_event_flags_set.c
Normal file
620
common/src/tx_event_flags_set.c
Normal file
@ -0,0 +1,620 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_set PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets the specified flags in the event group based on */
|
||||
/* the set option specified. All threads suspended on the group whose */
|
||||
/* get request can now be satisfied are resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to group control block */
|
||||
/* flags_to_set Event flags to set */
|
||||
/* set_option Specified either AND or OR */
|
||||
/* operation on the event flags */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Always returns success */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
TX_THREAD *satisfied_list;
|
||||
TX_THREAD *last_satisfied;
|
||||
TX_THREAD *suspended_list;
|
||||
UINT suspended_count;
|
||||
ULONG current_event_flags;
|
||||
ULONG requested_flags;
|
||||
ULONG flags_satisfied;
|
||||
ULONG *suspend_info_ptr;
|
||||
UINT and_request;
|
||||
UINT get_option;
|
||||
UINT clear_request;
|
||||
UINT preempt_check;
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
UINT interrupted_set_request;
|
||||
#endif
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*events_set_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *notify_group_ptr);
|
||||
#endif
|
||||
|
||||
|
||||
/* Disable interrupts to remove the semaphore from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total event flags set counter. */
|
||||
_tx_event_flags_performance_set_count++;
|
||||
|
||||
/* Increment the number of event flags sets on this semaphore. */
|
||||
group_ptr -> tx_event_flags_group_performance_set_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET, group_ptr, flags_to_set, set_option, group_ptr -> tx_event_flags_group_suspended_count, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_EVENT_FLAGS_SET_INSERT
|
||||
|
||||
/* Determine how to set this group's event flags. */
|
||||
if ((set_option & TX_EVENT_FLAGS_AND_MASK) == TX_AND)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Set interrupted set request flag to false. */
|
||||
interrupted_set_request = TX_FALSE;
|
||||
|
||||
/* Determine if the suspension list is being processed by an interrupted
|
||||
set request. */
|
||||
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
if (group_ptr -> tx_event_flags_group_suspension_list == TX_NULL)
|
||||
{
|
||||
|
||||
/* Set the interrupted set request flag. */
|
||||
interrupted_set_request = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Was a set request interrupted? */
|
||||
if (interrupted_set_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* A previous set operation was interrupted, we need to defer the
|
||||
event clearing until the set operation is complete. */
|
||||
|
||||
/* Remember the events to clear. */
|
||||
group_ptr -> tx_event_flags_group_delayed_clear =
|
||||
group_ptr -> tx_event_flags_group_delayed_clear | ~flags_to_set;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Previous set operation was not interrupted, simply clear the
|
||||
specified flags by "ANDing" the flags into the current events
|
||||
of the group. */
|
||||
group_ptr -> tx_event_flags_group_current =
|
||||
group_ptr -> tx_event_flags_group_current & flags_to_set;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this event flag group. */
|
||||
events_set_notify = group_ptr -> tx_event_flags_group_set_notify;
|
||||
#endif
|
||||
|
||||
/* "OR" the flags into the current events of the group. */
|
||||
group_ptr -> tx_event_flags_group_current =
|
||||
group_ptr -> tx_event_flags_group_current | flags_to_set;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Determine if there are any delayed flags to clear. */
|
||||
if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Yes, we need to neutralize the delayed clearing as well. */
|
||||
group_ptr -> tx_event_flags_group_delayed_clear =
|
||||
group_ptr -> tx_event_flags_group_delayed_clear & ~flags_to_set;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clear the preempt check flag. */
|
||||
preempt_check = TX_FALSE;
|
||||
|
||||
/* Pickup the thread suspended count. */
|
||||
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||||
|
||||
/* Determine if there are any threads suspended on the event flag group. */
|
||||
if (group_ptr -> tx_event_flags_group_suspension_list != TX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if there is just a single thread waiting on the event
|
||||
flag group. */
|
||||
if (suspended_count == ((UINT) 1))
|
||||
{
|
||||
|
||||
/* Single thread waiting for event flags. Bypass the multiple thread
|
||||
logic. */
|
||||
|
||||
/* Setup thread pointer. */
|
||||
thread_ptr = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
|
||||
/* Pickup the current event flags. */
|
||||
current_event_flags = group_ptr -> tx_event_flags_group_current;
|
||||
|
||||
/* Pickup the suspend information. */
|
||||
requested_flags = thread_ptr -> tx_thread_suspend_info;
|
||||
|
||||
/* Pickup the suspend option. */
|
||||
get_option = thread_ptr -> tx_thread_suspend_option;
|
||||
|
||||
/* Isolate the AND selection. */
|
||||
and_request = (get_option & TX_AND);
|
||||
|
||||
/* Check for AND condition. All flags must be present to satisfy request. */
|
||||
if (and_request == TX_AND)
|
||||
{
|
||||
|
||||
/* AND request is present. */
|
||||
|
||||
/* Calculate the flags present. */
|
||||
flags_satisfied = (current_event_flags & requested_flags);
|
||||
|
||||
/* Determine if they satisfy the AND request. */
|
||||
if (flags_satisfied != requested_flags)
|
||||
{
|
||||
|
||||
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||||
flags_satisfied = ((ULONG) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* OR request is present. Simply or the requested flags and the current flags. */
|
||||
flags_satisfied = (current_event_flags & requested_flags);
|
||||
}
|
||||
|
||||
/* Determine if the request is satisfied. */
|
||||
if (flags_satisfied != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Yes, resume the thread and apply any event flag
|
||||
clearing. */
|
||||
|
||||
/* Set the preempt check flag. */
|
||||
preempt_check = TX_TRUE;
|
||||
|
||||
/* Return the actual event flags that satisfied the request. */
|
||||
suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
*suspend_info_ptr = current_event_flags;
|
||||
|
||||
/* Pickup the clear bit. */
|
||||
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||||
|
||||
/* Determine whether or not clearing needs to take place. */
|
||||
if (clear_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, clear the flags that satisfied this request. */
|
||||
group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & (~requested_flags);
|
||||
}
|
||||
|
||||
/* Clear the suspension information in the event flag group. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||||
group_ptr -> tx_event_flags_group_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts to remove the semaphore from the created list. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Otherwise, the event flag requests of multiple threads must be
|
||||
examined. */
|
||||
|
||||
/* Setup thread pointer, keep a local copy of the head pointer. */
|
||||
suspended_list = group_ptr -> tx_event_flags_group_suspension_list;
|
||||
thread_ptr = suspended_list;
|
||||
|
||||
/* Clear the suspended list head pointer to thwart manipulation of
|
||||
the list in ISR's while we are processing here. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
|
||||
|
||||
/* Setup the satisfied thread pointers. */
|
||||
satisfied_list = TX_NULL;
|
||||
last_satisfied = TX_NULL;
|
||||
|
||||
/* Pickup the current event flags. */
|
||||
current_event_flags = group_ptr -> tx_event_flags_group_current;
|
||||
|
||||
/* Disable preemption while we process the suspended list. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Loop to examine all of the suspended threads. */
|
||||
do
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
|
||||
/* Determine if we need to reset the search. */
|
||||
if (group_ptr -> tx_event_flags_group_reset_search != TX_FALSE)
|
||||
{
|
||||
|
||||
/* Clear the reset search flag. */
|
||||
group_ptr -> tx_event_flags_group_reset_search = TX_FALSE;
|
||||
|
||||
/* Move the thread pointer to the beginning of the search list. */
|
||||
thread_ptr = suspended_list;
|
||||
|
||||
/* Reset the suspended count. */
|
||||
suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
|
||||
|
||||
/* Update the current events with any new ones that might
|
||||
have been set in a nested set events call from an ISR. */
|
||||
current_event_flags = current_event_flags | group_ptr -> tx_event_flags_group_current;
|
||||
}
|
||||
|
||||
/* Save next thread pointer. */
|
||||
next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Pickup the suspend information. */
|
||||
requested_flags = thread_ptr -> tx_thread_suspend_info;
|
||||
|
||||
/* Pickup this thread's suspension get option. */
|
||||
get_option = thread_ptr -> tx_thread_suspend_option;
|
||||
|
||||
/* Isolate the AND selection. */
|
||||
and_request = (get_option & TX_AND);
|
||||
|
||||
/* Check for AND condition. All flags must be present to satisfy request. */
|
||||
if (and_request == TX_AND)
|
||||
{
|
||||
|
||||
/* AND request is present. */
|
||||
|
||||
/* Calculate the flags present. */
|
||||
flags_satisfied = (current_event_flags & requested_flags);
|
||||
|
||||
/* Determine if they satisfy the AND request. */
|
||||
if (flags_satisfied != requested_flags)
|
||||
{
|
||||
|
||||
/* No, not all the requested flags are present. Clear the flags present variable. */
|
||||
flags_satisfied = ((ULONG) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* OR request is present. Simply or the requested flags and the current flags. */
|
||||
flags_satisfied = (current_event_flags & requested_flags);
|
||||
}
|
||||
|
||||
/* Check to see if the thread had a timeout or wait abort during the event search processing.
|
||||
If so, just set the flags satisfied to ensure the processing here removes the thread from
|
||||
the suspension list. */
|
||||
if (thread_ptr -> tx_thread_state != TX_EVENT_FLAG)
|
||||
{
|
||||
|
||||
/* Simply set the satisfied flags to 1 in order to remove the thread from the suspension list. */
|
||||
flags_satisfied = ((ULONG) 1);
|
||||
}
|
||||
|
||||
/* Determine if the request is satisfied. */
|
||||
if (flags_satisfied != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Yes, this request can be handled now. */
|
||||
|
||||
/* Set the preempt check flag. */
|
||||
preempt_check = TX_TRUE;
|
||||
|
||||
/* Determine if the thread is still suspended on the event flag group. If not, a wait
|
||||
abort must have been done from an ISR. */
|
||||
if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
|
||||
{
|
||||
|
||||
/* Return the actual event flags that satisfied the request. */
|
||||
suspend_info_ptr = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
*suspend_info_ptr = current_event_flags;
|
||||
|
||||
/* Pickup the clear bit. */
|
||||
clear_request = (get_option & TX_EVENT_FLAGS_CLEAR_MASK);
|
||||
|
||||
/* Determine whether or not clearing needs to take place. */
|
||||
if (clear_request == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, clear the flags that satisfied this request. */
|
||||
group_ptr -> tx_event_flags_group_current = group_ptr -> tx_event_flags_group_current & ~requested_flags;
|
||||
}
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
}
|
||||
|
||||
/* We need to remove the thread from the suspension list and place it in the
|
||||
expired list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
suspended_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Update the list head pointer, if removing the head of the
|
||||
list. */
|
||||
if (suspended_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Yes, head pointer needs to be updated. */
|
||||
suspended_list = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
group_ptr -> tx_event_flags_group_suspended_count--;
|
||||
|
||||
/* Place this thread on the expired list. */
|
||||
if (satisfied_list == TX_NULL)
|
||||
{
|
||||
|
||||
/* First thread on the satisfied list. */
|
||||
satisfied_list = thread_ptr;
|
||||
last_satisfied = thread_ptr;
|
||||
|
||||
/* Setup initial next pointer. */
|
||||
thread_ptr -> tx_thread_suspended_next = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not the first thread on the satisfied list. */
|
||||
|
||||
/* Link it up at the end. */
|
||||
last_satisfied -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = TX_NULL;
|
||||
last_satisfied = thread_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy next thread pointer to working thread ptr. */
|
||||
thread_ptr = next_thread_ptr;
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
} while (suspended_count != TX_NO_SUSPENSIONS);
|
||||
|
||||
/* Setup the group's suspension list head again. */
|
||||
group_ptr -> tx_event_flags_group_suspension_list = suspended_list;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Determine if there is any delayed event clearing to perform. */
|
||||
if (group_ptr -> tx_event_flags_group_delayed_clear != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Perform the delayed event clearing. */
|
||||
group_ptr -> tx_event_flags_group_current =
|
||||
group_ptr -> tx_event_flags_group_current & ~(group_ptr -> tx_event_flags_group_delayed_clear);
|
||||
|
||||
/* Clear the delayed event flag clear value. */
|
||||
group_ptr -> tx_event_flags_group_delayed_clear = ((ULONG) 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the satisfied list, setup initial thread pointer. */
|
||||
thread_ptr = satisfied_list;
|
||||
while(thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Get next pointer first. */
|
||||
next_thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupt posture. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move next thread to current. */
|
||||
thread_ptr = next_thread_ptr;
|
||||
}
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release thread preemption disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Determine if we need to set the reset search field. */
|
||||
if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* We interrupted a search of an event flag group suspension
|
||||
list. Make sure we reset the search. */
|
||||
group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (events_set_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application event flags set notification. */
|
||||
(events_set_notify)(group_ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine if a check for preemption is necessary. */
|
||||
if (preempt_check == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, one or more threads were resumed, check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
107
common/src/tx_event_flags_set_notify.c
Normal file
107
common/src/tx_event_flags_set_notify.c
Normal file
@ -0,0 +1,107 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Event Flags */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_event_flags.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_event_flags_set_notify PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application callback function that is */
|
||||
/* called whenever an event flag is set in this group. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* group_ptr Pointer to group control block*/
|
||||
/* group_put_notify Application callback function */
|
||||
/* (TX_NULL disables notify) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Service return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr))
|
||||
{
|
||||
|
||||
#ifdef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
TX_EVENT_FLAGS_GROUP_NOT_USED(group_ptr);
|
||||
TX_EVENT_FLAGS_SET_NOTIFY_NOT_USED(events_set_notify);
|
||||
|
||||
/* Feature is not enabled, return error. */
|
||||
return(TX_FEATURE_NOT_ENABLED);
|
||||
#else
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_EVENT_FLAGS_SET_NOTIFY, group_ptr, 0, 0, 0, TX_TRACE_EVENT_FLAGS_EVENTS)
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_EL_EVENT_FLAGS_SET_NOTIFY_INSERT
|
||||
|
||||
/* Setup event flag group set notification callback function. */
|
||||
group_ptr -> tx_event_flags_group_set_notify = events_set_notify;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success to caller. */
|
||||
return(TX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
150
common/src/tx_initialize_high_level.c
Normal file
150
common/src/tx_initialize_high_level.c
Normal file
@ -0,0 +1,150 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
|
||||
/* Determine if in-line initialization is required. */
|
||||
#ifdef TX_INLINE_INITIALIZATION
|
||||
#define TX_INVOKE_INLINE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
#include "tx_semaphore.h"
|
||||
#include "tx_queue.h"
|
||||
#include "tx_event_flags.h"
|
||||
#include "tx_mutex.h"
|
||||
#include "tx_block_pool.h"
|
||||
#include "tx_byte_pool.h"
|
||||
|
||||
|
||||
/* Define the unused memory pointer. The value of the first available
|
||||
memory address is placed in this variable in the low-level
|
||||
initialization function. The content of this variable is passed
|
||||
to the application's system definition function. */
|
||||
|
||||
VOID *_tx_initialize_unused_memory;
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_high_level PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for initializing all of the other */
|
||||
/* components in the ThreadX real-time kernel. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_initialize Initialize the thread control */
|
||||
/* component */
|
||||
/* _tx_timer_initialize Initialize the timer control */
|
||||
/* component */
|
||||
/* _tx_semaphore_initialize Initialize the semaphore control */
|
||||
/* component */
|
||||
/* _tx_queue_initialize Initialize the queue control */
|
||||
/* component */
|
||||
/* _tx_event_flags_initialize Initialize the event flags control*/
|
||||
/* component */
|
||||
/* _tx_block_pool_initialize Initialize the block pool control */
|
||||
/* component */
|
||||
/* _tx_byte_pool_initialize Initialize the byte pool control */
|
||||
/* component */
|
||||
/* _tx_mutex_initialize Initialize the mutex control */
|
||||
/* component */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter Kernel entry function */
|
||||
/* _tx_initialize_kernel_setup Early kernel setup function that */
|
||||
/* is optionally called by */
|
||||
/* compiler's startup code. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_initialize_high_level(VOID)
|
||||
{
|
||||
|
||||
/* Initialize event tracing, if enabled. */
|
||||
TX_TRACE_INITIALIZE
|
||||
|
||||
/* Initialize the event log, if enabled. */
|
||||
TX_EL_INITIALIZE
|
||||
|
||||
/* Call the thread control initialization function. */
|
||||
_tx_thread_initialize();
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
|
||||
/* Call the timer control initialization function. */
|
||||
_tx_timer_initialize();
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Call the semaphore initialization function. */
|
||||
_tx_semaphore_initialize();
|
||||
|
||||
/* Call the queue initialization function. */
|
||||
_tx_queue_initialize();
|
||||
|
||||
/* Call the event flag initialization function. */
|
||||
_tx_event_flags_initialize();
|
||||
|
||||
/* Call the block pool initialization function. */
|
||||
_tx_block_pool_initialize();
|
||||
|
||||
/* Call the byte pool initialization function. */
|
||||
_tx_byte_pool_initialize();
|
||||
|
||||
/* Call the mutex initialization function. */
|
||||
_tx_mutex_initialize();
|
||||
#endif
|
||||
}
|
||||
|
148
common/src/tx_initialize_kernel_enter.c
Normal file
148
common/src/tx_initialize_kernel_enter.c
Normal file
@ -0,0 +1,148 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
|
||||
/* Define any port-specific scheduling data structures. */
|
||||
|
||||
TX_PORT_SPECIFIC_DATA
|
||||
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
TX_SAFETY_CRITICAL_EXCEPTION_HANDLER
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the first ThreadX function called during */
|
||||
/* initialization. It is called from the application's "main()" */
|
||||
/* function. It is important to note that this routine never */
|
||||
/* returns. The processing of this function is relatively simple: */
|
||||
/* it calls several ThreadX initialization functions (if needed), */
|
||||
/* calls the application define function, and then invokes the */
|
||||
/* scheduler. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Low-level initialization */
|
||||
/* _tx_initialize_high_level High-level initialization */
|
||||
/* tx_application_define Application define function */
|
||||
/* _tx_thread_scheduler ThreadX scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* main Application main program */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_initialize_kernel_enter(VOID)
|
||||
{
|
||||
|
||||
/* Determine if the compiler has pre-initialized ThreadX. */
|
||||
if (_tx_thread_system_state != TX_INITIALIZE_ALMOST_DONE)
|
||||
{
|
||||
|
||||
/* No, the initialization still needs to take place. */
|
||||
|
||||
/* Ensure that the system state variable is set to indicate
|
||||
initialization is in progress. Note that this variable is
|
||||
later used to represent interrupt nesting. */
|
||||
_tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
|
||||
|
||||
/* Call any port specific preprocessing. */
|
||||
TX_PORT_SPECIFIC_PRE_INITIALIZATION
|
||||
|
||||
/* Invoke the low-level initialization to handle all processor specific
|
||||
initialization issues. */
|
||||
_tx_initialize_low_level();
|
||||
|
||||
/* Invoke the high-level initialization to exercise all of the
|
||||
ThreadX components and the application's initialization
|
||||
function. */
|
||||
_tx_initialize_high_level();
|
||||
|
||||
/* Call any port specific post-processing. */
|
||||
TX_PORT_SPECIFIC_POST_INITIALIZATION
|
||||
}
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_INITIALIZE_KERNEL_ENTER_EXTENSION
|
||||
|
||||
/* Ensure that the system state variable is set to indicate
|
||||
initialization is in progress. Note that this variable is
|
||||
later used to represent interrupt nesting. */
|
||||
_tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
|
||||
|
||||
/* Call the application provided initialization function. Pass the
|
||||
first available memory address to it. */
|
||||
tx_application_define(_tx_initialize_unused_memory);
|
||||
|
||||
/* Set the system state in preparation for entering the thread
|
||||
scheduler. */
|
||||
_tx_thread_system_state = TX_INITIALIZE_IS_FINISHED;
|
||||
|
||||
/* Call any port specific pre-scheduler processing. */
|
||||
TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
|
||||
|
||||
/* Enter the scheduling loop to start executing threads! */
|
||||
_tx_thread_schedule();
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
|
||||
/* If we ever get here, raise safety critical exception. */
|
||||
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
|
||||
#endif
|
||||
}
|
||||
|
100
common/src/tx_initialize_kernel_setup.c
Normal file
100
common/src/tx_initialize_kernel_setup.c
Normal file
@ -0,0 +1,100 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_setup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the compiler's startup code to make */
|
||||
/* ThreadX objects accessible to the compiler's library. If this */
|
||||
/* function is not called by the compiler, all ThreadX initialization */
|
||||
/* takes place from the kernel enter function defined previously. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Low-level initialization */
|
||||
/* _tx_initialize_high_level High-level initialization */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* startup code Compiler startup code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_initialize_kernel_setup(VOID)
|
||||
{
|
||||
|
||||
/* Ensure that the system state variable is set to indicate
|
||||
initialization is in progress. Note that this variable is
|
||||
later used to represent interrupt nesting. */
|
||||
_tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
|
||||
|
||||
/* Call any port specific preprocessing. */
|
||||
TX_PORT_SPECIFIC_PRE_INITIALIZATION
|
||||
|
||||
/* Invoke the low-level initialization to handle all processor specific
|
||||
initialization issues. */
|
||||
_tx_initialize_low_level();
|
||||
|
||||
/* Invoke the high-level initialization to exercise all of the
|
||||
ThreadX components and the application's initialization
|
||||
function. */
|
||||
_tx_initialize_high_level();
|
||||
|
||||
/* Call any port specific post-processing. */
|
||||
TX_PORT_SPECIFIC_POST_INITIALIZATION
|
||||
|
||||
/* Set the system state to indicate initialization is almost done. */
|
||||
_tx_thread_system_state = TX_INITIALIZE_ALMOST_DONE;
|
||||
}
|
||||
|
833
common/src/tx_misra.c
Normal file
833
common/src/tx_misra.c
Normal file
@ -0,0 +1,833 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** ThreadX MISRA Compliance */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** _tx_version_id */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_THREAD_INIT
|
||||
//CHAR _tx_version_id[100] = "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX 6.0 MISRA C Compliant *";
|
||||
#endif
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_trace.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size)
|
||||
{
|
||||
memset(ptr, value, size);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount)
|
||||
{
|
||||
ptr = ptr + amount;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount)
|
||||
{
|
||||
ptr = ptr - amount;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2)
|
||||
{
|
||||
|
||||
ULONG value;
|
||||
|
||||
value = ptr1 - ptr2;
|
||||
return(value);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr)
|
||||
{
|
||||
return((ULONG) ptr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount)
|
||||
{
|
||||
ptr = ptr + amount;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount)
|
||||
{
|
||||
|
||||
ptr = ptr - amount;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2)
|
||||
{
|
||||
ULONG value;
|
||||
|
||||
value = ptr1 - ptr2;
|
||||
return(value);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID *_tx_misra_ulong_to_pointer_convert(ULONG input)
|
||||
{
|
||||
|
||||
return((VOID *) input);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */
|
||||
/** UINT size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, UINT size)
|
||||
{
|
||||
|
||||
ULONG *s, *d;
|
||||
UINT z;
|
||||
|
||||
s = *source;
|
||||
d = *destination;
|
||||
z = size;
|
||||
|
||||
*(d) = *(s);
|
||||
(d)++;
|
||||
(s)++;
|
||||
if ((z) > ((UINT) 1))
|
||||
{
|
||||
(z)--;
|
||||
while ((z))
|
||||
{
|
||||
*(d) = *(s);
|
||||
(d)++;
|
||||
(s)++;
|
||||
(z)--;
|
||||
}
|
||||
}
|
||||
|
||||
*source = s;
|
||||
*destination = d;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */
|
||||
/** TX_TIMER_INTERNAL **ptr2); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, TX_TIMER_INTERNAL **ptr2)
|
||||
{
|
||||
|
||||
ULONG value;
|
||||
|
||||
value = ptr1 - ptr2;
|
||||
return(value);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */
|
||||
/** **ptr1, ULONG size); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL **ptr1, ULONG amount)
|
||||
{
|
||||
ptr1 = ptr1 + amount;
|
||||
return(ptr1);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */
|
||||
/** *internal_timer, TX_TIMER **user_timer); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL *internal_timer, TX_TIMER **user_timer)
|
||||
{
|
||||
|
||||
UCHAR *working_ptr;
|
||||
TX_TIMER *temp_timer;
|
||||
|
||||
|
||||
working_ptr = (UCHAR *) internal_timer;
|
||||
|
||||
temp_timer = (TX_TIMER *) working_ptr;
|
||||
working_ptr = working_ptr - (((UCHAR *) &temp_timer -> tx_timer_internal) - ((UCHAR *) &temp_timer -> tx_timer_id));
|
||||
*user_timer = (TX_TIMER *) working_ptr;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */
|
||||
/** VOID **highest_stack); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, VOID **highest_stack)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_DISABLE
|
||||
if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID))
|
||||
{
|
||||
if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) *highest_stack))
|
||||
{
|
||||
*highest_stack = (thread_ptr) -> tx_thread_stack_ptr;
|
||||
}
|
||||
if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) ||
|
||||
(*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) ||
|
||||
(((ULONG *) *highest_stack) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start)))
|
||||
{
|
||||
TX_RESTORE
|
||||
_tx_thread_stack_error_handler((thread_ptr));
|
||||
TX_DISABLE
|
||||
}
|
||||
if (*(((ULONG *) *highest_stack) - 1) != TX_STACK_FILL)
|
||||
{
|
||||
TX_RESTORE
|
||||
_tx_thread_stack_analyze((thread_ptr));
|
||||
TX_DISABLE
|
||||
}
|
||||
}
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID _tx_misra_trace_event_insert(ULONG event_id, */
|
||||
/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */
|
||||
/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID _tx_misra_trace_event_insert(ULONG event_id, VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, ULONG time_stamp)
|
||||
{
|
||||
|
||||
TX_TRACE_BUFFER_ENTRY *trace_event_ptr;
|
||||
ULONG trace_system_state;
|
||||
ULONG trace_priority;
|
||||
TX_THREAD *trace_thread_ptr;
|
||||
|
||||
|
||||
trace_event_ptr = _tx_trace_buffer_current_ptr;
|
||||
if ((trace_event_ptr) && (_tx_trace_event_enable_bits & ((ULONG) (filter))))
|
||||
{
|
||||
TX_TRACE_PORT_EXTENSION
|
||||
trace_system_state = (ULONG) _tx_thread_system_state;
|
||||
trace_thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
if (trace_system_state == 0)
|
||||
{
|
||||
trace_priority = trace_thread_ptr -> tx_thread_priority;
|
||||
trace_priority = trace_priority | 0x80000000UL | (trace_thread_ptr -> tx_thread_preempt_threshold << 16);
|
||||
}
|
||||
else if (trace_system_state < 0xF0F0F0F0UL)
|
||||
{
|
||||
trace_priority = (ULONG) trace_thread_ptr;
|
||||
trace_thread_ptr = (TX_THREAD *) 0xFFFFFFFFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace_thread_ptr = (TX_THREAD *) 0xF0F0F0F0UL;
|
||||
trace_priority = 0;
|
||||
}
|
||||
trace_event_ptr -> tx_trace_buffer_entry_thread_pointer = (ULONG) trace_thread_ptr;
|
||||
trace_event_ptr -> tx_trace_buffer_entry_thread_priority = (ULONG) trace_priority;
|
||||
trace_event_ptr -> tx_trace_buffer_entry_event_id = (ULONG) (event_id);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_time_stamp = (ULONG) (time_stamp);
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
trace_event_ptr -> tx_trace_buffer_entry_info_1 = (ULONG) (info_field_1);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_info_2 = (ULONG) (info_field_2);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_info_3 = (ULONG) (info_field_3);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_info_4 = (ULONG) (info_field_4);
|
||||
#else
|
||||
trace_event_ptr -> tx_trace_buffer_entry_information_field_1 = (ULONG) (info_field_1);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_information_field_2 = (ULONG) (info_field_2);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_information_field_3 = (ULONG) (info_field_3);
|
||||
trace_event_ptr -> tx_trace_buffer_entry_information_field_4 = (ULONG) (info_field_4);
|
||||
#endif
|
||||
trace_event_ptr++;
|
||||
if (trace_event_ptr >= _tx_trace_buffer_end_ptr)
|
||||
{
|
||||
trace_event_ptr = _tx_trace_buffer_start_ptr;
|
||||
_tx_trace_buffer_current_ptr = trace_event_ptr;
|
||||
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr;
|
||||
if (_tx_trace_full_notify_function)
|
||||
(_tx_trace_full_notify_function)((VOID *) _tx_trace_header_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tx_trace_buffer_current_ptr = trace_event_ptr;
|
||||
_tx_trace_header_ptr -> tx_trace_header_buffer_current_pointer = (ULONG) trace_event_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ULONG _tx_misra_time_stamp_get(VOID); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
ULONG _tx_misra_time_stamp_get(VOID)
|
||||
{
|
||||
|
||||
/* Return time stamp. */
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_always_true(void); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
UINT _tx_misra_always_true(void)
|
||||
{
|
||||
return(TX_TRUE);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */
|
||||
/** */
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr)
|
||||
{
|
||||
|
||||
/* Return an indirect UCHAR pointer. */
|
||||
return((UCHAR **) ((VOID *) return_ptr));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return an indirect UCHAR pointer. */
|
||||
return((UCHAR **) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************/
|
||||
/***********************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */
|
||||
/** */
|
||||
/***********************************************************************************/
|
||||
/***********************************************************************************/
|
||||
UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pool));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/** */
|
||||
/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a block pool pointer. */
|
||||
return((TX_BLOCK_POOL *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
/** */
|
||||
/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((TX_BLOCK_POOL *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************/
|
||||
/**************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/**************************************************************************************/
|
||||
/**************************************************************************************/
|
||||
UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR **) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
/** */
|
||||
/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a byte pool pointer. */
|
||||
return((TX_BYTE_POOL *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */
|
||||
/** */
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pool));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
/** */
|
||||
/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return an align time pointer. */
|
||||
return((ALIGN_TYPE *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************************/
|
||||
/****************************************************************************************************/
|
||||
/** */
|
||||
/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/****************************************************************************************************/
|
||||
/****************************************************************************************************/
|
||||
TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a byte pool pointer. */
|
||||
return((TX_BYTE_POOL **) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************/
|
||||
/**************************************************************************************************/
|
||||
/** */
|
||||
/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/**************************************************************************************************/
|
||||
/**************************************************************************************************/
|
||||
TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return event flags pointer. */
|
||||
return((TX_EVENT_FLAGS_GROUP *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/** */
|
||||
/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a ULONG pointer. */
|
||||
return((ULONG *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
/** */
|
||||
/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return a mutex pointer. */
|
||||
return((TX_MUTEX *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** UINT _tx_misra_status_get(UINT status); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
UINT _tx_misra_status_get(UINT status)
|
||||
{
|
||||
|
||||
/* Return a successful status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
/** */
|
||||
/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return queue pointer. */
|
||||
return((TX_QUEUE *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/****************************************************************************************/
|
||||
/** */
|
||||
/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */
|
||||
/** */
|
||||
/****************************************************************************************/
|
||||
/****************************************************************************************/
|
||||
TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer)
|
||||
{
|
||||
|
||||
/* Return semaphore pointer. */
|
||||
return((TX_SEMAPHORE *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a VOID pointer. */
|
||||
return((VOID *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************/
|
||||
/*********************************************************************************/
|
||||
/** */
|
||||
/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */
|
||||
/** */
|
||||
/*********************************************************************************/
|
||||
/*********************************************************************************/
|
||||
TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value)
|
||||
{
|
||||
|
||||
/* Return a thread pointer. */
|
||||
return((TX_THREAD *) ((VOID *) value));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************************/
|
||||
/***************************************************************************************************/
|
||||
/** */
|
||||
/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */
|
||||
/** */
|
||||
/***************************************************************************************************/
|
||||
/***************************************************************************************************/
|
||||
VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer)
|
||||
{
|
||||
|
||||
/* Return a void pointer. */
|
||||
return((VOID *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
/** */
|
||||
/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */
|
||||
/** */
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer)
|
||||
{
|
||||
|
||||
/* Return a CHAR pointer. */
|
||||
return((CHAR *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************/
|
||||
/**********************************************************************************/
|
||||
/** */
|
||||
/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */
|
||||
/** */
|
||||
/**********************************************************************************/
|
||||
/**********************************************************************************/
|
||||
TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer)
|
||||
{
|
||||
|
||||
/* Return thread pointer. */
|
||||
return((TX_THREAD *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */
|
||||
/** */
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/** */
|
||||
/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return an object entry pointer. */
|
||||
return((TX_TRACE_OBJECT_ENTRY *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/** */
|
||||
/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a trace header pointer. */
|
||||
return((TX_TRACE_HEADER *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a trace buffer entry pointer. */
|
||||
return((TX_TRACE_BUFFER_ENTRY *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
/** */
|
||||
/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */
|
||||
/** */
|
||||
/***********************************************************************************************/
|
||||
/***********************************************************************************************/
|
||||
UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer)
|
||||
{
|
||||
|
||||
/* Return a UCHAR pointer. */
|
||||
return((UCHAR *) ((VOID *) pointer));
|
||||
}
|
||||
|
||||
|
||||
|
313
common/src/tx_mutex_cleanup.c
Normal file
313
common/src/tx_mutex_cleanup.c
Normal file
@ -0,0 +1,313 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes mutex timeout and thread terminate */
|
||||
/* actions that require the mutex data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_MUTEX *mutex_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the mutex. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_mutex_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to mutex control block. */
|
||||
mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for NULL mutex pointer. */
|
||||
if (mutex_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if the mutex ID is valid. */
|
||||
if (mutex_ptr -> tx_mutex_id == TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to mutex control block. */
|
||||
mutex_ptr = TX_VOID_TO_MUTEX_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Yes, we still have thread suspension! */
|
||||
|
||||
/* Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
mutex_ptr -> tx_mutex_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = mutex_ptr -> tx_mutex_suspended_count;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (mutex_ptr -> tx_mutex_suspension_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread still suspended on the mutex.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_mutex_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this semaphore. */
|
||||
mutex_ptr -> tx_mutex_performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_NOT_AVAILABLE;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_thread_release PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function releases all mutexes owned by the thread. This */
|
||||
/* function is called when the thread completes or is terminated. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread's control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_mutex_put Release the mutex */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_shell_entry Thread completion processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_mutex_thread_release(TX_THREAD *thread_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_MUTEX *mutex_ptr;
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
UINT status;
|
||||
#endif
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Loop to look at all the mutexes. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Pickup the mutex head pointer. */
|
||||
mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list;
|
||||
|
||||
/* Determine if there is a mutex. */
|
||||
if (mutex_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, set the ownership count to 1. */
|
||||
mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
/* Release the mutex. */
|
||||
do
|
||||
{
|
||||
status = _tx_mutex_put(mutex_ptr);
|
||||
} while (status != TX_SUCCESS);
|
||||
#else
|
||||
_tx_mutex_put(mutex_ptr);
|
||||
#endif
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Move to the next mutex. */
|
||||
mutex_ptr = thread_ptr -> tx_thread_owned_mutex_list;
|
||||
}
|
||||
} while (mutex_ptr != TX_NULL);
|
||||
|
||||
/* Restore preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
146
common/src/tx_mutex_create.c
Normal file
146
common/src/tx_mutex_create.c
Normal file
@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a mutex with optional priority inheritance as */
|
||||
/* specified in this call. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block*/
|
||||
/* name_ptr Pointer to mutex name */
|
||||
/* inherit Priority inheritance option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_MUTEX *next_mutex;
|
||||
TX_MUTEX *previous_mutex;
|
||||
|
||||
|
||||
/* Initialize mutex control block to all zeros. */
|
||||
TX_MEMSET(mutex_ptr, 0, (sizeof(TX_MUTEX)));
|
||||
|
||||
/* Setup the basic mutex fields. */
|
||||
mutex_ptr -> tx_mutex_name = name_ptr;
|
||||
mutex_ptr -> tx_mutex_inherit = inherit;
|
||||
|
||||
/* Disable interrupts to place the mutex on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the mutex ID to make it valid. */
|
||||
mutex_ptr -> tx_mutex_id = TX_MUTEX_ID;
|
||||
|
||||
/* Setup the thread mutex release function pointer. */
|
||||
_tx_thread_mutex_release = &(_tx_mutex_thread_release);
|
||||
|
||||
/* Place the mutex on the list of created mutexes. First,
|
||||
check for an empty list. */
|
||||
if (_tx_mutex_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created mutex list is empty. Add mutex to empty list. */
|
||||
_tx_mutex_created_ptr = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_created_next = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_created_previous = mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_mutex = _tx_mutex_created_ptr;
|
||||
previous_mutex = next_mutex -> tx_mutex_created_previous;
|
||||
|
||||
/* Place the new mutex in the list. */
|
||||
next_mutex -> tx_mutex_created_previous = mutex_ptr;
|
||||
previous_mutex -> tx_mutex_created_next = mutex_ptr;
|
||||
|
||||
/* Setup this mutex's next and previous created links. */
|
||||
mutex_ptr -> tx_mutex_created_previous = previous_mutex;
|
||||
mutex_ptr -> tx_mutex_created_next = next_mutex;
|
||||
}
|
||||
|
||||
/* Increment the ownership count. */
|
||||
_tx_mutex_created_count++;
|
||||
|
||||
/* Optional mutex create extended processing. */
|
||||
TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_MUTEX, mutex_ptr, name_ptr, inherit, 0)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_CREATE, mutex_ptr, inherit, TX_POINTER_TO_ULONG_CONVERT(&next_mutex), 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
243
common/src/tx_mutex_delete.c
Normal file
243
common/src/tx_mutex_delete.c
Normal file
@ -0,0 +1,243 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified mutex. All threads */
|
||||
/* suspended on the mutex are resumed with the TX_DELETED status */
|
||||
/* code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_mutex_put Release an owned mutex */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *owner_thread;
|
||||
UINT suspended_count;
|
||||
TX_MUTEX *next_mutex;
|
||||
TX_MUTEX *previous_mutex;
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
UINT status;
|
||||
#endif
|
||||
|
||||
/* Disable interrupts to remove the mutex from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_DELETE, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Optional mutex delete extended processing. */
|
||||
TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(mutex_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_DELETE_INSERT
|
||||
|
||||
/* Clear the mutex ID to make it invalid. */
|
||||
mutex_ptr -> tx_mutex_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the created count. */
|
||||
_tx_mutex_created_count--;
|
||||
|
||||
/* See if the mutex is the only one on the list. */
|
||||
if (_tx_mutex_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created mutex, just set the created list to NULL. */
|
||||
_tx_mutex_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_mutex = mutex_ptr -> tx_mutex_created_next;
|
||||
previous_mutex = mutex_ptr -> tx_mutex_created_previous;
|
||||
next_mutex -> tx_mutex_created_previous = previous_mutex;
|
||||
previous_mutex -> tx_mutex_created_next = next_mutex;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_mutex_created_ptr == mutex_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_mutex_created_ptr = next_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
|
||||
mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
|
||||
suspended_count = mutex_ptr -> tx_mutex_suspended_count;
|
||||
mutex_ptr -> tx_mutex_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
|
||||
/* Determine if the mutex is currently on a thread's ownership list. */
|
||||
|
||||
/* Setup pointer to owner of mutex. */
|
||||
owner_thread = mutex_ptr -> tx_mutex_owner;
|
||||
|
||||
/* Determine if there is a valid thread pointer. */
|
||||
if (owner_thread != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, remove this mutex from the owned list. */
|
||||
|
||||
/* Set the ownership count to 1. */
|
||||
mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
/* Release the mutex. */
|
||||
do
|
||||
{
|
||||
status = _tx_mutex_put(mutex_ptr);
|
||||
} while (status != TX_SUCCESS);
|
||||
#else
|
||||
_tx_mutex_put(mutex_ptr);
|
||||
#endif
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the mutex list to resume any and all threads suspended
|
||||
on this mutex. */
|
||||
while (suspended_count != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_MUTEX_DELETE_PORT_COMPLETION(mutex_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
409
common/src/tx_mutex_get.c
Normal file
409
common/src/tx_mutex_get.c
Normal file
@ -0,0 +1,409 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the specified mutex. If the calling thread */
|
||||
/* already owns the mutex, an ownership count is simply increased. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_suspend Suspend thread service */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* _tx_mutex_priority_change Inherit thread priority */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_MUTEX *next_mutex;
|
||||
TX_MUTEX *previous_mutex;
|
||||
TX_THREAD *mutex_owner;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Disable interrupts to get an instance from the mutex. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total mutex get counter. */
|
||||
_tx_mutex_performance_get_count++;
|
||||
|
||||
/* Increment the number of attempts to get this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance_get_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_GET_INSERT
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Determine if this mutex is available. */
|
||||
if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Set the ownership count to 1. */
|
||||
mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
|
||||
|
||||
/* Remember that the calling thread owns the mutex. */
|
||||
mutex_ptr -> tx_mutex_owner = thread_ptr;
|
||||
|
||||
/* Determine if the thread pointer is valid. */
|
||||
if (thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Determine if priority inheritance is required. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Remember the current priority of thread. */
|
||||
mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority;
|
||||
|
||||
/* Setup the highest priority waiting thread. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = ((UINT) TX_MAX_PRIORITIES);
|
||||
}
|
||||
|
||||
/* Pickup next mutex pointer, which is the head of the list. */
|
||||
next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
|
||||
|
||||
/* Determine if this thread owns any other mutexes that have priority inheritance. */
|
||||
if (next_mutex != TX_NULL)
|
||||
{
|
||||
|
||||
/* Non-empty list. Link up the mutex. */
|
||||
|
||||
/* Pickup the next and previous mutex pointer. */
|
||||
previous_mutex = next_mutex -> tx_mutex_owned_previous;
|
||||
|
||||
/* Place the owned mutex in the list. */
|
||||
next_mutex -> tx_mutex_owned_previous = mutex_ptr;
|
||||
previous_mutex -> tx_mutex_owned_next = mutex_ptr;
|
||||
|
||||
/* Setup this mutex's next and previous created links. */
|
||||
mutex_ptr -> tx_mutex_owned_previous = previous_mutex;
|
||||
mutex_ptr -> tx_mutex_owned_next = next_mutex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The owned mutex list is empty. Add mutex to empty list. */
|
||||
thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_owned_next = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_owned_previous = mutex_ptr;
|
||||
}
|
||||
|
||||
/* Increment the number of mutexes owned counter. */
|
||||
thread_ptr -> tx_thread_owned_mutex_count++;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
|
||||
/* Otherwise, see if the owning thread is trying to obtain the same mutex. */
|
||||
else if (mutex_ptr -> tx_mutex_owner == thread_ptr)
|
||||
{
|
||||
|
||||
/* The owning thread is requesting the mutex again, just
|
||||
increment the ownership count. */
|
||||
mutex_ptr -> tx_mutex_ownership_count++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_NOT_AVAILABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
/* Pickup the mutex owner. */
|
||||
mutex_owner = mutex_ptr -> tx_mutex_owner;
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total mutex suspension counter. */
|
||||
_tx_mutex_performance_suspension_count++;
|
||||
|
||||
/* Increment the number of suspensions on this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance_suspension_count++;
|
||||
|
||||
/* Determine if a priority inversion is present. */
|
||||
if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, priority inversion is present! */
|
||||
|
||||
/* Increment the total mutex priority inversions counter. */
|
||||
_tx_mutex_performance_priority_inversion_count++;
|
||||
|
||||
/* Increment the number of priority inversions on this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance_priority_inversion_count++;
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the number of total thread priority inversions. */
|
||||
_tx_thread_performance_priority_inversion_count++;
|
||||
|
||||
/* Increment the number of priority inversions for this thread. */
|
||||
thread_ptr -> tx_thread_performance_priority_inversion_count++;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_mutex_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this mutex control
|
||||
block. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) mutex_ptr;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = mutex_ptr -> tx_mutex_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the suspension count. */
|
||||
mutex_ptr -> tx_mutex_suspended_count++;
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_MUTEX_SUSP;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Determine if we need to raise the priority of the thread
|
||||
owning the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Determine if this is the highest priority to raise for this mutex. */
|
||||
if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Remember this priority. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
|
||||
/* Determine if we have to update inherit priority level of the mutex owner. */
|
||||
if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
|
||||
{
|
||||
|
||||
/* Remember the new priority inheritance priority. */
|
||||
mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
|
||||
/* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */
|
||||
if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, raise the suspended, owning thread's priority to that
|
||||
of the current thread. */
|
||||
_tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total mutex priority inheritance counter. */
|
||||
_tx_mutex_performance__priority_inheritance_count++;
|
||||
|
||||
/* Increment the number of priority inheritance situations on this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Determine if we need to raise the priority of the thread
|
||||
owning the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Determine if this is the highest priority to raise for this mutex. */
|
||||
if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Remember this priority. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
|
||||
/* Determine if we have to update inherit priority level of the mutex owner. */
|
||||
if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
|
||||
{
|
||||
|
||||
/* Remember the new priority inheritance priority. */
|
||||
mutex_owner -> tx_thread_inherit_priority = thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
|
||||
/* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority. */
|
||||
if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, raise the suspended, owning thread's priority to that
|
||||
of the current thread. */
|
||||
_tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total mutex priority inheritance counter. */
|
||||
_tx_mutex_performance__priority_inheritance_count++;
|
||||
|
||||
/* Increment the number of priority inheritance situations on this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
147
common/src/tx_mutex_info_get.c
Normal file
147
common/src/tx_mutex_info_get.c
Normal file
@ -0,0 +1,147 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified mutex. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* name Destination for the mutex name */
|
||||
/* count Destination for the owner count */
|
||||
/* owner Destination for the owner's */
|
||||
/* thread control block pointer */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on the mutex */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_mutex Destination for pointer to next */
|
||||
/* mutex on the created list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,
|
||||
TX_THREAD **first_suspended, ULONG *suspended_count,
|
||||
TX_MUTEX **next_mutex)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the mutex. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = mutex_ptr -> tx_mutex_name;
|
||||
}
|
||||
|
||||
/* Retrieve the current ownership count of the mutex. */
|
||||
if (count != TX_NULL)
|
||||
{
|
||||
|
||||
*count = ((ULONG) mutex_ptr -> tx_mutex_ownership_count);
|
||||
}
|
||||
|
||||
/* Retrieve the current owner of the mutex. */
|
||||
if (owner != TX_NULL)
|
||||
{
|
||||
|
||||
*owner = mutex_ptr -> tx_mutex_owner;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this mutex. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = mutex_ptr -> tx_mutex_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this mutex. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) mutex_ptr -> tx_mutex_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next mutex created. */
|
||||
if (next_mutex != TX_NULL)
|
||||
{
|
||||
|
||||
*next_mutex = mutex_ptr -> tx_mutex_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
141
common/src/tx_mutex_initialize.c
Normal file
141
common/src/tx_mutex_initialize.c
Normal file
@ -0,0 +1,141 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Locate mutex component data in this file. */
|
||||
|
||||
/* Define the head pointer of the created mutex list. */
|
||||
|
||||
TX_MUTEX * _tx_mutex_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created mutexes. */
|
||||
|
||||
ULONG _tx_mutex_created_count;
|
||||
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of mutex puts. */
|
||||
|
||||
ULONG _tx_mutex_performance_put_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex gets. */
|
||||
|
||||
ULONG _tx_mutex_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex suspensions. */
|
||||
|
||||
ULONG _tx_mutex_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of mutex timeouts. */
|
||||
|
||||
ULONG _tx_mutex_performance_timeout_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inversions. */
|
||||
|
||||
ULONG _tx_mutex_performance_priority_inversion_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inheritance conditions. */
|
||||
|
||||
ULONG _tx_mutex_performance__priority_inheritance_count;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the mutex component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_mutex_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created mutexes list and the
|
||||
number of mutexes created. */
|
||||
_tx_mutex_created_ptr = TX_NULL;
|
||||
_tx_mutex_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize the mutex performance counters. */
|
||||
_tx_mutex_performance_put_count = ((ULONG) 0);
|
||||
_tx_mutex_performance_get_count = ((ULONG) 0);
|
||||
_tx_mutex_performance_suspension_count = ((ULONG) 0);
|
||||
_tx_mutex_performance_timeout_count = ((ULONG) 0);
|
||||
_tx_mutex_performance_priority_inversion_count = ((ULONG) 0);
|
||||
_tx_mutex_performance__priority_inheritance_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
230
common/src/tx_mutex_performance_info_get.c
Normal file
230
common/src/tx_mutex_performance_info_get.c
Normal file
@ -0,0 +1,230 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_mutex.h"
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* mutex. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* puts Destination for the number of */
|
||||
/* puts on to this mutex */
|
||||
/* gets Destination for the number of */
|
||||
/* gets on this mutex */
|
||||
/* suspensions Destination for the number of */
|
||||
/* suspensions on this mutex */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this mutex */
|
||||
/* inversions Destination for number of priority*/
|
||||
/* inversions on this mutex */
|
||||
/* inheritances Destination for number of priority*/
|
||||
/* inheritances on this mutex */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets,
|
||||
ULONG *suspensions, ULONG *timeouts, ULONG *inversions, ULONG *inheritances)
|
||||
{
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default status to success. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (mutex_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Mutex pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the mutex ID is invalid. */
|
||||
else if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Mutex pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_INFO_GET, mutex_ptr, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of puts on this mutex. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
*puts = mutex_ptr -> tx_mutex_performance_put_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of gets on this mutex. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = mutex_ptr -> tx_mutex_performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of suspensions on this mutex. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = mutex_ptr -> tx_mutex_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of timeouts on this mutex. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = mutex_ptr -> tx_mutex_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of priority inversions on this mutex. */
|
||||
if (inversions != TX_NULL)
|
||||
{
|
||||
|
||||
*inversions = mutex_ptr -> tx_mutex_performance_priority_inversion_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of priority inheritances on this mutex. */
|
||||
if (inheritances != TX_NULL)
|
||||
{
|
||||
|
||||
*inheritances = mutex_ptr -> tx_mutex_performance__priority_inheritance_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (mutex_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (inversions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (inheritances != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
205
common/src/tx_mutex_performance_system_info_get.c
Normal file
205
common/src/tx_mutex_performance_system_info_get.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_mutex.h"
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves system mutex performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* puts Destination for total number of */
|
||||
/* mutex puts */
|
||||
/* gets Destination for total number of */
|
||||
/* mutex gets */
|
||||
/* suspensions Destination for total number of */
|
||||
/* mutex suspensions */
|
||||
/* timeouts Destination for total number of */
|
||||
/* mutex timeouts */
|
||||
/* inversions Destination for total number of */
|
||||
/* mutex priority inversions */
|
||||
/* inheritances Destination for total number of */
|
||||
/* mutex priority inheritances */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions,
|
||||
ULONG *timeouts, ULONG *inversions, ULONG *inheritances)
|
||||
{
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of mutex puts. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
*puts = _tx_mutex_performance_put_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of mutex gets. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = _tx_mutex_performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of mutex suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_mutex_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of mutex timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_mutex_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of mutex priority inversions. */
|
||||
if (inversions != TX_NULL)
|
||||
{
|
||||
|
||||
*inversions = _tx_mutex_performance_priority_inversion_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of mutex priority inheritances. */
|
||||
if (inheritances != TX_NULL)
|
||||
{
|
||||
|
||||
*inheritances = _tx_mutex_performance__priority_inheritance_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (inversions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (inheritances != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
265
common/src/tx_mutex_prioritize.c
Normal file
265
common/src/tx_mutex_prioritize.c
Normal file
@ -0,0 +1,265 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_prioritize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places the highest priority suspended thread at the */
|
||||
/* front of the suspension list. All other threads remain in the same */
|
||||
/* FIFO suspension order. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *priority_thread_ptr;
|
||||
TX_THREAD *head_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT list_changed;
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
UINT status;
|
||||
#endif
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PRIORITIZE, mutex_ptr, mutex_ptr -> tx_mutex_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_PRIORITIZE_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = mutex_ptr -> tx_mutex_suspended_count;
|
||||
|
||||
/* Determine if there are fewer than 2 suspended threads. */
|
||||
if (suspended_count < ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if there how many threads are suspended on this mutex. */
|
||||
else if (suspended_count == ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Pickup the head pointer and the next pointer. */
|
||||
head_ptr = mutex_ptr -> tx_mutex_suspension_list;
|
||||
next_thread = head_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Determine if the next suspended thread has a higher priority. */
|
||||
if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
|
||||
{
|
||||
|
||||
/* Yes, move the list head to the next thread. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = next_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = mutex_ptr -> tx_mutex_suspension_list;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the list changed flag to false. */
|
||||
list_changed = TX_FALSE;
|
||||
|
||||
/* Search through the list to find the highest priority thread. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Is the current thread higher priority? */
|
||||
if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, remember that this thread is the highest priority. */
|
||||
priority_thread_ptr = thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if any changes to the list have occurred while
|
||||
interrupts were enabled. */
|
||||
|
||||
/* Is the list head the same? */
|
||||
if (head_ptr != mutex_ptr -> tx_mutex_suspension_list)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Is the suspended count the same? */
|
||||
if (suspended_count != mutex_ptr -> tx_mutex_suspended_count)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the list has changed. */
|
||||
if (list_changed == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Move the thread pointer to the next thread. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = mutex_ptr -> tx_mutex_suspension_list;
|
||||
suspended_count = mutex_ptr -> tx_mutex_suspended_count;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Reset the list changed flag. */
|
||||
list_changed = TX_FALSE;
|
||||
}
|
||||
|
||||
} while (thread_ptr != head_ptr);
|
||||
|
||||
/* Release preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Now determine if the highest priority thread is at the front
|
||||
of the list. */
|
||||
if (priority_thread_ptr != head_ptr)
|
||||
{
|
||||
|
||||
/* No, we need to move the highest priority suspended thread to the
|
||||
front of the list. */
|
||||
|
||||
/* First, remove the highest priority thread by updating the
|
||||
adjacent suspended threads. */
|
||||
next_thread = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Now, link the highest priority thread at the front of the list. */
|
||||
previous_thread = head_ptr -> tx_thread_suspended_previous;
|
||||
priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
|
||||
priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
|
||||
head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
|
||||
|
||||
/* Move the list head pointer to the highest priority suspended thread. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = priority_thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
|
||||
/* Initialize status to success. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Define extended processing option. */
|
||||
status = TX_MUTEX_PRIORITIZE_MISRA_EXTENSION(status);
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#else
|
||||
|
||||
/* Return successful completion. */
|
||||
return(TX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
328
common/src/tx_mutex_priority_change.c
Normal file
328
common/src/tx_mutex_priority_change.c
Normal file
@ -0,0 +1,328 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_priority_change PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function changes the priority of the specified thread for the */
|
||||
/* priority inheritance option of the mutex service. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread to suspend */
|
||||
/* new_priority New thread priority */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_thread_system_suspend Suspend thread */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_mutex_get Inherit priority */
|
||||
/* _tx_mutex_put Restore previous priority */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_THREAD *execute_ptr;
|
||||
TX_THREAD *next_execute_ptr;
|
||||
UINT original_priority;
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
ULONG priority_bit;
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
UINT map_index;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Lockout interrupts while the thread is being suspended. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
|
||||
/* Determine if this thread is currently ready. */
|
||||
if (thread_ptr -> tx_thread_state != TX_READY)
|
||||
{
|
||||
|
||||
/* Change thread priority to the new mutex priority-inheritance priority. */
|
||||
thread_ptr -> tx_thread_priority = new_priority;
|
||||
|
||||
/* Determine how to setup the thread's preemption-threshold. */
|
||||
if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
|
||||
{
|
||||
|
||||
/* Change thread preemption-threshold to the user's preemption-threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Change the thread preemption-threshold to the new threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = new_priority;
|
||||
}
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Pickup the next thread to execute. */
|
||||
execute_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Save the original priority. */
|
||||
original_priority = thread_ptr -> tx_thread_priority;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the preempt disable flag. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_SUSPENDED;
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
|
||||
|
||||
/* At this point, the preempt disable flag is still set, so we still have
|
||||
protection against all preemption. */
|
||||
|
||||
/* Change thread priority to the new mutex priority-inheritance priority. */
|
||||
thread_ptr -> tx_thread_priority = new_priority;
|
||||
|
||||
/* Determine how to setup the thread's preemption-threshold. */
|
||||
if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
|
||||
{
|
||||
|
||||
/* Change thread preemption-threshold to the user's preemption-threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Change the thread preemption-threshold to the new threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = new_priority;
|
||||
}
|
||||
|
||||
/* Resume the thread with the new priority. */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Decrement the preempt disable flag. */
|
||||
_tx_thread_preempt_disable--;
|
||||
#else
|
||||
|
||||
/* Increment the preempt disable flag. */
|
||||
_tx_thread_preempt_disable = _tx_thread_preempt_disable + ((UINT) 2);
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_SUSPENDED;
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = ((ULONG) 0);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* The thread is ready and must first be removed from the list. Call the
|
||||
system suspend function to accomplish this. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* At this point, the preempt disable flag is still set, so we still have
|
||||
protection against all preemption. */
|
||||
|
||||
/* Change thread priority to the new mutex priority-inheritance priority. */
|
||||
thread_ptr -> tx_thread_priority = new_priority;
|
||||
|
||||
/* Determine how to setup the thread's preemption-threshold. */
|
||||
if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
|
||||
{
|
||||
|
||||
/* Change thread preemption-threshold to the user's preemption-threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Change the thread preemption-threshold to the new threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = new_priority;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread with the new priority. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_MUTEX_PRIORITY_CHANGE_EXTENSION
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
|
||||
/* Pickup the next thread to execute. */
|
||||
next_execute_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Determine if this thread is not the next thread to execute. */
|
||||
if (thread_ptr != next_execute_ptr)
|
||||
{
|
||||
|
||||
/* Make sure the thread is still ready. */
|
||||
if (thread_ptr -> tx_thread_state == TX_READY)
|
||||
{
|
||||
|
||||
/* Now check and see if this thread has an equal or higher priority. */
|
||||
if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Now determine if this thread was the previously executing thread. */
|
||||
if (thread_ptr == execute_ptr)
|
||||
{
|
||||
|
||||
/* Yes, this thread was previously executing before we temporarily suspended and resumed
|
||||
it in order to change the priority. A lower or same priority thread cannot be the next thread
|
||||
to execute in this case since this thread really didn't suspend. Simply reset the execute
|
||||
pointer to this thread. */
|
||||
_tx_thread_execute_ptr = thread_ptr;
|
||||
|
||||
/* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */
|
||||
if (original_priority < new_priority)
|
||||
{
|
||||
|
||||
/* Ensure that this thread is placed at the front of the priority list. */
|
||||
_tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Now determine if this thread's preemption-threshold needs to be enforced. */
|
||||
if (thread_ptr -> tx_thread_preempt_threshold < thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, preemption-threshold is in force for this thread. */
|
||||
|
||||
/* Compare the next thread to execute thread's priority against the thread's preemption-threshold. */
|
||||
if (thread_ptr -> tx_thread_preempt_threshold <= next_execute_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* We must swap execute pointers to enforce the preemption-threshold of a thread coming out of
|
||||
priority inheritance. */
|
||||
_tx_thread_execute_ptr = thread_ptr;
|
||||
|
||||
/* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list. */
|
||||
if (original_priority < new_priority)
|
||||
{
|
||||
|
||||
/* Ensure that this thread is placed at the front of the priority list. */
|
||||
_tx_thread_priority_list[thread_ptr -> tx_thread_priority] = thread_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
/* In this case, we need to mark the preempted map to indicate a thread executed above the
|
||||
preemption-threshold. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
|
||||
/* Calculate the index into the bit map array. */
|
||||
map_index = (next_execute_ptr -> tx_thread_priority)/ ((UINT) 32);
|
||||
|
||||
/* Set the active bit to remember that the preempt map has something set. */
|
||||
TX_DIV32_BIT_SET(next_execute_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit;
|
||||
#endif
|
||||
|
||||
/* Remember that this thread was preempted by a thread above the thread's threshold. */
|
||||
TX_MOD32_BIT_SET(next_execute_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
654
common/src/tx_mutex_put.c
Normal file
654
common/src/tx_mutex_put.c
Normal file
@ -0,0 +1,654 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Mutex */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_mutex_put PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function puts back an instance of the specified mutex. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* mutex_ptr Pointer to mutex control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Success completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_mutex_priority_change Restore previous thread priority */
|
||||
/* _tx_mutex_prioritize Prioritize the mutex suspension */
|
||||
/* _tx_mutex_thread_release Release all thread's mutexes */
|
||||
/* _tx_mutex_delete Release ownership upon mutex */
|
||||
/* deletion */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_mutex_put(TX_MUTEX *mutex_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *old_owner;
|
||||
UINT old_priority;
|
||||
UINT status;
|
||||
TX_MUTEX *next_mutex;
|
||||
TX_MUTEX *previous_mutex;
|
||||
UINT owned_count;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *current_thread;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
TX_THREAD *suspended_thread;
|
||||
UINT inheritance_priority;
|
||||
|
||||
|
||||
/* Setup status to indicate the processing is not complete. */
|
||||
status = TX_NOT_DONE;
|
||||
|
||||
/* Disable interrupts to put an instance back to the mutex. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total mutex put counter. */
|
||||
_tx_mutex_performance_put_count++;
|
||||
|
||||
/* Increment the number of attempts to put this mutex. */
|
||||
mutex_ptr -> tx_mutex_performance_put_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PUT, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_POINTER_TO_ULONG_CONVERT(&old_priority), TX_TRACE_MUTEX_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_MUTEX_PUT_INSERT
|
||||
|
||||
/* Determine if this mutex is owned. */
|
||||
if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Pickup the owning thread pointer. */
|
||||
thread_ptr = mutex_ptr -> tx_mutex_owner;
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(current_thread)
|
||||
|
||||
/* Check to see if the mutex is owned by the calling thread. */
|
||||
if (mutex_ptr -> tx_mutex_owner != current_thread)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is set, indicating that
|
||||
the caller is not the application but from ThreadX. In such
|
||||
cases, the thread mutex owner does not need to match. */
|
||||
if (_tx_thread_preempt_disable == ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Invalid mutex release. */
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Caller does not own the mutex. */
|
||||
status = TX_NOT_OWNED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if we should continue. */
|
||||
if (status == TX_NOT_DONE)
|
||||
{
|
||||
|
||||
/* Decrement the mutex ownership count. */
|
||||
mutex_ptr -> tx_mutex_ownership_count--;
|
||||
|
||||
/* Determine if the mutex is still owned by the current thread. */
|
||||
if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Mutex is still owned, just return successful status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Check for a NULL thread pointer, which can only happen during initialization. */
|
||||
if (thread_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Mutex is now available, return successful status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* The mutex is now available. */
|
||||
|
||||
/* Remove this mutex from the owned mutex list. */
|
||||
|
||||
/* Decrement the ownership count. */
|
||||
thread_ptr -> tx_thread_owned_mutex_count--;
|
||||
|
||||
/* Determine if this mutex was the only one on the list. */
|
||||
if (thread_ptr -> tx_thread_owned_mutex_count == ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Yes, the list is empty. Simply set the head pointer to NULL. */
|
||||
thread_ptr -> tx_thread_owned_mutex_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, there are more mutexes on the list. */
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_mutex = mutex_ptr -> tx_mutex_owned_next;
|
||||
previous_mutex = mutex_ptr -> tx_mutex_owned_previous;
|
||||
next_mutex -> tx_mutex_owned_previous = previous_mutex;
|
||||
previous_mutex -> tx_mutex_owned_next = next_mutex;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (thread_ptr -> tx_thread_owned_mutex_list == mutex_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
thread_ptr -> tx_thread_owned_mutex_list = next_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the simple, non-suspension, non-priority inheritance case is present. */
|
||||
if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL)
|
||||
{
|
||||
|
||||
/* Is this a priority inheritance mutex? */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Yes, we are done - set the mutex owner to NULL. */
|
||||
mutex_ptr -> tx_mutex_owner = TX_NULL;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Mutex is now available, return successful status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the processing is complete. */
|
||||
if (status == TX_NOT_DONE)
|
||||
{
|
||||
|
||||
/* Initialize original owner and thread priority. */
|
||||
old_owner = TX_NULL;
|
||||
old_priority = thread_ptr -> tx_thread_user_priority;
|
||||
|
||||
/* Does this mutex support priority inheritance? */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
|
||||
/* Default the inheritance priority to disabled. */
|
||||
inheritance_priority = ((UINT) TX_MAX_PRIORITIES);
|
||||
|
||||
/* Search the owned mutexes for this thread to determine the highest priority for this
|
||||
former mutex owner to return to. */
|
||||
next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
|
||||
while (next_mutex != TX_NULL)
|
||||
{
|
||||
|
||||
/* Does this mutex support priority inheritance? */
|
||||
if (next_mutex -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Determine if highest priority field of the mutex is higher than the priority to
|
||||
restore. */
|
||||
if (next_mutex -> tx_mutex_highest_priority_waiting < inheritance_priority)
|
||||
{
|
||||
|
||||
/* Use this priority to return releasing thread to. */
|
||||
inheritance_priority = next_mutex -> tx_mutex_highest_priority_waiting;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move mutex pointer to the next mutex in the list. */
|
||||
next_mutex = next_mutex -> tx_mutex_owned_next;
|
||||
|
||||
/* Are we at the end of the list? */
|
||||
if (next_mutex == thread_ptr -> tx_thread_owned_mutex_list)
|
||||
{
|
||||
|
||||
/* Yes, set the next mutex to NULL. */
|
||||
next_mutex = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Undo the temporarily preemption disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
#endif
|
||||
|
||||
/* Set the inherit priority to that of the highest priority thread waiting on the mutex. */
|
||||
thread_ptr -> tx_thread_inherit_priority = inheritance_priority;
|
||||
|
||||
/* Determine if the inheritance priority is less than the default old priority. */
|
||||
if (inheritance_priority < old_priority)
|
||||
{
|
||||
|
||||
/* Yes, update the old priority. */
|
||||
old_priority = inheritance_priority;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if priority inheritance is in effect and there are one or more
|
||||
threads suspended on the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count > ((UINT) 1))
|
||||
{
|
||||
|
||||
/* Is priority inheritance in effect? */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, this code is simply to ensure the highest priority thread is positioned
|
||||
at the front of the suspension list. */
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
|
||||
/* Call the mutex prioritize processing to ensure the
|
||||
highest priority thread is resumed. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
do
|
||||
{
|
||||
status = _tx_mutex_prioritize(mutex_ptr);
|
||||
} while (status != TX_SUCCESS);
|
||||
#else
|
||||
_tx_mutex_prioritize(mutex_ptr);
|
||||
#endif
|
||||
|
||||
/* At this point, the highest priority thread is at the
|
||||
front of the suspension list. */
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_MUTEX_PUT_EXTENSION_1
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Back off the preemption disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Now determine if there are any threads still waiting on the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL)
|
||||
{
|
||||
|
||||
/* No, there are no longer any threads waiting on the mutex. */
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
|
||||
/* Mutex is not owned, but it is possible that a thread that
|
||||
caused a priority inheritance to occur is no longer waiting
|
||||
on the mutex. */
|
||||
|
||||
/* Setup the highest priority waiting thread. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES;
|
||||
|
||||
/* Determine if we need to restore priority. */
|
||||
if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority)
|
||||
{
|
||||
|
||||
/* Yes, restore the priority of thread. */
|
||||
_tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority);
|
||||
}
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Back off the preemption disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
#endif
|
||||
|
||||
/* Set the mutex owner to NULL. */
|
||||
mutex_ptr -> tx_mutex_owner = TX_NULL;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Set status to success. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Pickup the thread at the front of the suspension list. */
|
||||
thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
|
||||
|
||||
/* Save the previous ownership information, if inheritance is
|
||||
in effect. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Remember the old mutex owner. */
|
||||
old_owner = mutex_ptr -> tx_mutex_owner;
|
||||
|
||||
/* Setup owner thread priority information. */
|
||||
mutex_ptr -> tx_mutex_original_priority = thread_ptr -> tx_thread_priority;
|
||||
|
||||
/* Setup the highest priority waiting thread. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES;
|
||||
}
|
||||
|
||||
/* Determine how many mutexes are owned by this thread. */
|
||||
owned_count = thread_ptr -> tx_thread_owned_mutex_count;
|
||||
|
||||
/* Determine if this thread owns any other mutexes that have priority inheritance. */
|
||||
if (owned_count == ((UINT) 0))
|
||||
{
|
||||
|
||||
/* The owned mutex list is empty. Add mutex to empty list. */
|
||||
thread_ptr -> tx_thread_owned_mutex_list = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_owned_next = mutex_ptr;
|
||||
mutex_ptr -> tx_mutex_owned_previous = mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Non-empty list. Link up the mutex. */
|
||||
|
||||
/* Pickup tail pointer. */
|
||||
next_mutex = thread_ptr -> tx_thread_owned_mutex_list;
|
||||
previous_mutex = next_mutex -> tx_mutex_owned_previous;
|
||||
|
||||
/* Place the owned mutex in the list. */
|
||||
next_mutex -> tx_mutex_owned_previous = mutex_ptr;
|
||||
previous_mutex -> tx_mutex_owned_next = mutex_ptr;
|
||||
|
||||
/* Setup this mutex's next and previous created links. */
|
||||
mutex_ptr -> tx_mutex_owned_previous = previous_mutex;
|
||||
mutex_ptr -> tx_mutex_owned_next = next_mutex;
|
||||
}
|
||||
|
||||
/* Increment the number of mutexes owned counter. */
|
||||
thread_ptr -> tx_thread_owned_mutex_count = owned_count + ((UINT) 1);
|
||||
|
||||
/* Mark the Mutex as owned and fill in the corresponding information. */
|
||||
mutex_ptr -> tx_mutex_ownership_count = (UINT) 1;
|
||||
mutex_ptr -> tx_mutex_owner = thread_ptr;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
mutex_ptr -> tx_mutex_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = mutex_ptr -> tx_mutex_suspended_count;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
mutex_ptr -> tx_mutex_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Determine if priority inheritance is enabled for this mutex. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, priority inheritance is requested. */
|
||||
|
||||
/* Determine if there are any more threads still suspended on the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Determine if there are more than one thread suspended on the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count > ((ULONG) 1))
|
||||
{
|
||||
|
||||
/* If so, prioritize the list so the highest priority thread is placed at the
|
||||
front of the suspension list. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
do
|
||||
{
|
||||
status = _tx_mutex_prioritize(mutex_ptr);
|
||||
} while (status != TX_SUCCESS);
|
||||
#else
|
||||
_tx_mutex_prioritize(mutex_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now, pickup the list head and set the priority. */
|
||||
|
||||
/* Determine if there still are threads suspended for this mutex. */
|
||||
suspended_thread = mutex_ptr -> tx_mutex_suspension_list;
|
||||
if (suspended_thread != TX_NULL)
|
||||
{
|
||||
|
||||
/* Setup the highest priority thread waiting on this mutex. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore previous priority needs to be restored after priority
|
||||
inheritance. */
|
||||
|
||||
/* Determine if we need to restore priority. */
|
||||
if (old_owner -> tx_thread_priority != old_priority)
|
||||
{
|
||||
|
||||
/* Restore priority of thread. */
|
||||
_tx_mutex_priority_change(old_owner, old_priority);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Determine if priority inheritance is enabled for this mutex. */
|
||||
if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, priority inheritance is requested. */
|
||||
|
||||
/* Determine if there are any more threads still suspended on the mutex. */
|
||||
if (mutex_ptr -> tx_mutex_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Prioritize the list so the highest priority thread is placed at the
|
||||
front of the suspension list. */
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
do
|
||||
{
|
||||
status = _tx_mutex_prioritize(mutex_ptr);
|
||||
} while (status != TX_SUCCESS);
|
||||
#else
|
||||
_tx_mutex_prioritize(mutex_ptr);
|
||||
#endif
|
||||
|
||||
/* Now, pickup the list head and set the priority. */
|
||||
|
||||
/* Optional processing extension. */
|
||||
TX_MUTEX_PUT_EXTENSION_2
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if there still are threads suspended for this mutex. */
|
||||
suspended_thread = mutex_ptr -> tx_mutex_suspension_list;
|
||||
if (suspended_thread != TX_NULL)
|
||||
{
|
||||
|
||||
/* Setup the highest priority thread waiting on this mutex. */
|
||||
mutex_ptr -> tx_mutex_highest_priority_waiting = suspended_thread -> tx_thread_priority;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Restore previous priority needs to be restored after priority
|
||||
inheritance. */
|
||||
|
||||
/* Is the priority different? */
|
||||
if (old_owner -> tx_thread_priority != old_priority)
|
||||
{
|
||||
|
||||
/* Restore the priority of thread. */
|
||||
_tx_mutex_priority_change(old_owner, old_priority);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Return a successful status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Caller does not own the mutex. */
|
||||
status = TX_NOT_OWNED;
|
||||
}
|
||||
|
||||
/* Return the completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
225
common/src/tx_queue_cleanup.c
Normal file
225
common/src/tx_queue_cleanup.c
Normal file
@ -0,0 +1,225 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes queue timeout and thread terminate */
|
||||
/* actions that require the queue data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_QUEUE *queue_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the queue. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_queue_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to queue control block. */
|
||||
queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for NULL queue pointer. */
|
||||
if (queue_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Is the queue ID valid? */
|
||||
if (queue_ptr -> tx_queue_id == TX_QUEUE_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to queue control block. */
|
||||
queue_ptr = TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Yes, we still have thread suspension! */
|
||||
|
||||
/* Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Decrement the suspended count. */
|
||||
queue_ptr -> tx_queue_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (queue_ptr -> tx_queue_suspension_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_QUEUE_SUSP)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread still suspended on the queue.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_queue_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this queue. */
|
||||
queue_ptr -> tx_queue_performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
|
||||
{
|
||||
|
||||
/* Queue full timeout! */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_QUEUE_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Queue empty timeout! */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_QUEUE_EMPTY;
|
||||
}
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
170
common/src/tx_queue_create.c
Normal file
170
common/src/tx_queue_create.c
Normal file
@ -0,0 +1,170 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a message queue. The message size and depth */
|
||||
/* of the queue is specified by the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* name_ptr Pointer to queue name */
|
||||
/* message_size Size of each queue message */
|
||||
/* queue_start Starting address of the queue area*/
|
||||
/* queue_size Number of bytes in the queue */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
|
||||
VOID *queue_start, ULONG queue_size)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
UINT capacity;
|
||||
UINT used_words;
|
||||
TX_QUEUE *next_queue;
|
||||
TX_QUEUE *previous_queue;
|
||||
|
||||
|
||||
/* Initialize queue control block to all zeros. */
|
||||
TX_MEMSET(queue_ptr, 0, (sizeof(TX_QUEUE)));
|
||||
|
||||
/* Setup the basic queue fields. */
|
||||
queue_ptr -> tx_queue_name = name_ptr;
|
||||
|
||||
/* Save the message size in the control block. */
|
||||
queue_ptr -> tx_queue_message_size = message_size;
|
||||
|
||||
/* Determine how many messages will fit in the queue area and the number
|
||||
of ULONGs used. */
|
||||
capacity = (UINT) (queue_size / ((ULONG) (((ULONG) message_size) * (sizeof(ULONG)))));
|
||||
used_words = capacity * message_size;
|
||||
|
||||
/* Save the starting address and calculate the ending address of
|
||||
the queue. Note that the ending address is really one past the
|
||||
end! */
|
||||
queue_ptr -> tx_queue_start = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
|
||||
queue_ptr -> tx_queue_end = TX_ULONG_POINTER_ADD(queue_ptr -> tx_queue_start, used_words);
|
||||
|
||||
/* Set the read and write pointers to the beginning of the queue
|
||||
area. */
|
||||
queue_ptr -> tx_queue_read = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
|
||||
queue_ptr -> tx_queue_write = TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
|
||||
|
||||
/* Setup the number of enqueued messages and the number of message
|
||||
slots available in the queue. */
|
||||
queue_ptr -> tx_queue_available_storage = (UINT) capacity;
|
||||
queue_ptr -> tx_queue_capacity = (UINT) capacity;
|
||||
|
||||
/* Disable interrupts to put the queue on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the queue ID to make it valid. */
|
||||
queue_ptr -> tx_queue_id = TX_QUEUE_ID;
|
||||
|
||||
/* Place the queue on the list of created queues. First,
|
||||
check for an empty list. */
|
||||
if (_tx_queue_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created queue list is empty. Add queue to empty list. */
|
||||
_tx_queue_created_ptr = queue_ptr;
|
||||
queue_ptr -> tx_queue_created_next = queue_ptr;
|
||||
queue_ptr -> tx_queue_created_previous = queue_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_queue = _tx_queue_created_ptr;
|
||||
previous_queue = next_queue -> tx_queue_created_previous;
|
||||
|
||||
/* Place the new queue in the list. */
|
||||
next_queue -> tx_queue_created_previous = queue_ptr;
|
||||
previous_queue -> tx_queue_created_next = queue_ptr;
|
||||
|
||||
/* Setup this queues's created links. */
|
||||
queue_ptr -> tx_queue_created_previous = previous_queue;
|
||||
queue_ptr -> tx_queue_created_next = next_queue;
|
||||
}
|
||||
|
||||
/* Increment the created queue count. */
|
||||
_tx_queue_created_count++;
|
||||
|
||||
/* Optional queue create extended processing. */
|
||||
TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, name_ptr, queue_size, message_size)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_CREATE, queue_ptr, message_size, TX_POINTER_TO_ULONG_CONVERT(queue_start), queue_size, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
206
common/src/tx_queue_delete.c
Normal file
206
common/src/tx_queue_delete.c
Normal file
@ -0,0 +1,206 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified queue. All threads suspended */
|
||||
/* on the queue are resumed with the TX_DELETED status code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_delete(TX_QUEUE *queue_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
UINT suspended_count;
|
||||
TX_QUEUE *next_queue;
|
||||
TX_QUEUE *previous_queue;
|
||||
|
||||
|
||||
/* Disable interrupts to remove the queue from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_DELETE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Optional queue delete extended processing. */
|
||||
TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(queue_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_DELETE_INSERT
|
||||
|
||||
/* Clear the queue ID to make it invalid. */
|
||||
queue_ptr -> tx_queue_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of created queues. */
|
||||
_tx_queue_created_count--;
|
||||
|
||||
/* See if the queue is the only one on the list. */
|
||||
if (_tx_queue_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created queue, just set the created list to NULL. */
|
||||
_tx_queue_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_queue = queue_ptr -> tx_queue_created_next;
|
||||
previous_queue = queue_ptr -> tx_queue_created_previous;
|
||||
next_queue -> tx_queue_created_previous = previous_queue;
|
||||
previous_queue -> tx_queue_created_next = next_queue;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_queue_created_ptr == queue_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_queue_created_ptr = next_queue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the queue list to resume any and all threads suspended
|
||||
on this queue. */
|
||||
while (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_QUEUE_DELETE_PORT_COMPLETION(queue_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
205
common/src/tx_queue_flush.c
Normal file
205
common/src/tx_queue_flush.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_flush PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function resets the specified queue, if there are any messages */
|
||||
/* in it. Messages waiting to be placed on the queue are also thrown */
|
||||
/* out. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_flush(TX_QUEUE *queue_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *suspension_list;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Initialize the suspended count and list. */
|
||||
suspended_count = TX_NO_SUSPENSIONS;
|
||||
suspension_list = TX_NULL;
|
||||
|
||||
/* Disable interrupts to reset various queue parameters. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FLUSH, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_FLUSH_INSERT
|
||||
|
||||
/* Determine if there is something on the queue. */
|
||||
if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
|
||||
{
|
||||
|
||||
/* Yes, there is something in the queue. */
|
||||
|
||||
/* Reset the queue parameters to erase all of the queued messages. */
|
||||
queue_ptr -> tx_queue_enqueued = TX_NO_MESSAGES;
|
||||
queue_ptr -> tx_queue_available_storage = queue_ptr -> tx_queue_capacity;
|
||||
queue_ptr -> tx_queue_read = queue_ptr -> tx_queue_start;
|
||||
queue_ptr -> tx_queue_write = queue_ptr -> tx_queue_start;
|
||||
|
||||
/* Now determine if there are any threads suspended on a full queue. */
|
||||
if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, there are threads suspended on this queue, they must be
|
||||
resumed! */
|
||||
|
||||
/* Copy the information into temporary variables. */
|
||||
suspension_list = queue_ptr -> tx_queue_suspension_list;
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Clear the queue variables. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
queue_ptr -> tx_queue_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the queue list to resume any and all threads suspended
|
||||
on this queue. */
|
||||
if (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Pickup the thread to resume. */
|
||||
thread_ptr = suspension_list;
|
||||
while (suspended_count != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Check for a NULL thread pointer. */
|
||||
if (thread_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Get out of the loop. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Resume the next suspended thread. */
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_SUCCESS. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr -> tx_thread_suspended_previous);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr -> tx_thread_suspended_previous);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Restore previous preempt posture. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
421
common/src/tx_queue_front_send.c
Normal file
421
common/src/tx_queue_front_send.c
Normal file
@ -0,0 +1,421 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_front_send PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places a message at the front of the specified queue. */
|
||||
/* If there is no room in the queue, this function returns the */
|
||||
/* queue full status. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* source_ptr Pointer to message source */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread routine */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_thread_system_suspend Suspend thread routine */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
ULONG *source;
|
||||
ULONG *destination;
|
||||
UINT size;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr);
|
||||
#endif
|
||||
|
||||
|
||||
/* Default the status to TX_SUCCESS. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Disable interrupts to place message in the queue. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total messages sent counter. */
|
||||
_tx_queue_performance_messages_sent_count++;
|
||||
|
||||
/* Increment the number of messages sent to this queue. */
|
||||
queue_ptr -> tx_queue_performance_messages_sent_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_FRONT_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_FRONT_SEND_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Now check for room in the queue for placing the new message in front. */
|
||||
if (queue_ptr -> tx_queue_available_storage != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Yes there is room in the queue. Now determine if there is a thread waiting
|
||||
for a message. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No thread suspended while waiting for a message from
|
||||
this queue. */
|
||||
|
||||
/* Adjust the read pointer since we are adding to the front of the
|
||||
queue. */
|
||||
|
||||
/* See if the read pointer is at the beginning of the queue area. */
|
||||
if (queue_ptr -> tx_queue_read == queue_ptr -> tx_queue_start)
|
||||
{
|
||||
|
||||
/* Adjust the read pointer to the last message at the end of the
|
||||
queue. */
|
||||
queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_end, queue_ptr -> tx_queue_message_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not at the beginning of the queue, just move back one message. */
|
||||
queue_ptr -> tx_queue_read = TX_ULONG_POINTER_SUB(queue_ptr -> tx_queue_read, queue_ptr -> tx_queue_message_size);
|
||||
}
|
||||
|
||||
/* Simply place the message in the queue. */
|
||||
|
||||
/* Reduce the amount of available storage. */
|
||||
queue_ptr -> tx_queue_available_storage--;
|
||||
|
||||
/* Increase the enqueued count. */
|
||||
queue_ptr -> tx_queue_enqueued++;
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
|
||||
destination = queue_ptr -> tx_queue_read;
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Thread suspended waiting for a message. Remove it and copy this message
|
||||
into its storage area. */
|
||||
thread_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
|
||||
destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the caller has requested suspension. */
|
||||
else if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_QUEUE_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Yes, suspension is requested. */
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this queue control
|
||||
block and the source pointer. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr;
|
||||
|
||||
/* Set the flag to true to indicate a queue front send suspension. */
|
||||
thread_ptr -> tx_thread_suspend_option = TX_TRUE;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Place this thread at the front of the suspension list, since it is a
|
||||
queue front send suspension. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = queue_ptr -> tx_queue_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
|
||||
/* Update the suspension list to put this thread in front, which will put
|
||||
the message that was removed in the proper relative order when room is
|
||||
made in the queue. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the suspended thread count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Check for a notify callback. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* No room in queue and no suspension requested, return error completion. */
|
||||
status = TX_QUEUE_FULL;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
145
common/src/tx_queue_info_get.c
Normal file
145
common/src/tx_queue_info_get.c
Normal file
@ -0,0 +1,145 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified queue. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* name Destination for the queue name */
|
||||
/* enqueued Destination for enqueued count */
|
||||
/* available_storage Destination for available storage */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on this queue */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_queue Destination for pointer to next */
|
||||
/* queue on the created list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage,
|
||||
TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the queue. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = queue_ptr -> tx_queue_name;
|
||||
}
|
||||
|
||||
/* Retrieve the number of messages currently in the queue. */
|
||||
if (enqueued != TX_NULL)
|
||||
{
|
||||
|
||||
*enqueued = (ULONG) queue_ptr -> tx_queue_enqueued;
|
||||
}
|
||||
|
||||
/* Retrieve the number of messages that will still fit in the queue. */
|
||||
if (available_storage != TX_NULL)
|
||||
{
|
||||
|
||||
*available_storage = (ULONG) queue_ptr -> tx_queue_available_storage;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this queue. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = queue_ptr -> tx_queue_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this queue. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) queue_ptr -> tx_queue_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next queue created. */
|
||||
if (next_queue != TX_NULL)
|
||||
{
|
||||
|
||||
*next_queue = queue_ptr -> tx_queue_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
138
common/src/tx_queue_initialize.c
Normal file
138
common/src/tx_queue_initialize.c
Normal file
@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Define the head pointer of the created queue list. */
|
||||
|
||||
TX_QUEUE * _tx_queue_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created queues. */
|
||||
|
||||
ULONG _tx_queue_created_count;
|
||||
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of messages sent. */
|
||||
|
||||
ULONG _tx_queue_performance_messages_sent_count;
|
||||
|
||||
|
||||
/* Define the total number of messages received. */
|
||||
|
||||
ULONG _tx_queue_performance__messages_received_count;
|
||||
|
||||
|
||||
/* Define the total number of queue empty suspensions. */
|
||||
|
||||
ULONG _tx_queue_performance_empty_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of queue full suspensions. */
|
||||
|
||||
ULONG _tx_queue_performance_full_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of queue full errors. */
|
||||
|
||||
ULONG _tx_queue_performance_full_error_count;
|
||||
|
||||
|
||||
/* Define the total number of queue timeouts. */
|
||||
|
||||
ULONG _tx_queue_performance_timeout_count;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the queue component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_queue_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created queue list and the
|
||||
number of queues created. */
|
||||
_tx_queue_created_ptr = TX_NULL;
|
||||
_tx_queue_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize the queue performance counters. */
|
||||
_tx_queue_performance_messages_sent_count = ((ULONG) 0);
|
||||
_tx_queue_performance__messages_received_count = ((ULONG) 0);
|
||||
_tx_queue_performance_empty_suspension_count = ((ULONG) 0);
|
||||
_tx_queue_performance_full_suspension_count = ((ULONG) 0);
|
||||
_tx_queue_performance_timeout_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
229
common/src/tx_queue_performance_info_get.c
Normal file
229
common/src/tx_queue_performance_info_get.c
Normal file
@ -0,0 +1,229 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_queue.h"
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* queue. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* messages_sent Destination for messages sent */
|
||||
/* messages_received Destination for messages received */
|
||||
/* empty_suspensions Destination for number of empty */
|
||||
/* queue suspensions */
|
||||
/* full_suspensions Destination for number of full */
|
||||
/* queue suspensions */
|
||||
/* full_errors Destination for queue full errors */
|
||||
/* returned - no suspension */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this queue */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received,
|
||||
ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (queue_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Queue pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the queue ID is invalid. */
|
||||
else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
|
||||
{
|
||||
|
||||
/* Queue pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_INFO_GET, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of messages sent to this queue. */
|
||||
if (messages_sent != TX_NULL)
|
||||
{
|
||||
|
||||
*messages_sent = queue_ptr -> tx_queue_performance_messages_sent_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of messages received from this queue. */
|
||||
if (messages_received != TX_NULL)
|
||||
{
|
||||
|
||||
*messages_received = queue_ptr -> tx_queue_performance_messages_received_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of empty queue suspensions on this queue. */
|
||||
if (empty_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*empty_suspensions = queue_ptr -> tx_queue_performance_empty_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of full queue suspensions on this queue. */
|
||||
if (full_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*full_suspensions = queue_ptr -> tx_queue_performance_full_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of full errors (no suspension!) on this queue. */
|
||||
if (full_errors != TX_NULL)
|
||||
{
|
||||
|
||||
*full_errors = queue_ptr -> tx_queue_performance_full_error_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of timeouts on this queue. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = queue_ptr -> tx_queue_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (queue_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (messages_sent != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (messages_received != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (empty_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (full_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (full_errors != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
205
common/src/tx_queue_performance_system_info_get.c
Normal file
205
common/src/tx_queue_performance_system_info_get.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_queue.h"
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves queue system performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* messages_sent Destination for total messages */
|
||||
/* sent */
|
||||
/* messages_received Destination for total messages */
|
||||
/* received */
|
||||
/* empty_suspensions Destination for total empty */
|
||||
/* queue suspensions */
|
||||
/* full_suspensions Destination for total full */
|
||||
/* queue suspensions */
|
||||
/* full_errors Destination for total queue full */
|
||||
/* errors returned - no suspension */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_performance_system_info_get(ULONG *messages_sent, ULONG *messages_received,
|
||||
ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of queue messages sent. */
|
||||
if (messages_sent != TX_NULL)
|
||||
{
|
||||
|
||||
*messages_sent = _tx_queue_performance_messages_sent_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of queue messages received. */
|
||||
if (messages_received != TX_NULL)
|
||||
{
|
||||
|
||||
*messages_received = _tx_queue_performance__messages_received_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of empty queue suspensions. */
|
||||
if (empty_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*empty_suspensions = _tx_queue_performance_empty_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of full queue suspensions. */
|
||||
if (full_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*full_suspensions = _tx_queue_performance_full_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of full errors. */
|
||||
if (full_errors != TX_NULL)
|
||||
{
|
||||
|
||||
*full_errors = _tx_queue_performance_full_error_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of queue timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_queue_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (messages_sent != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (messages_received != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (empty_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (full_suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (full_errors != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
249
common/src/tx_queue_prioritize.c
Normal file
249
common/src/tx_queue_prioritize.c
Normal file
@ -0,0 +1,249 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_prioritize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places the highest priority suspended thread at the */
|
||||
/* front of the suspension list. All other threads remain in the same */
|
||||
/* FIFO suspension order. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_prioritize(TX_QUEUE *queue_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *priority_thread_ptr;
|
||||
TX_THREAD *head_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT list_changed;
|
||||
|
||||
|
||||
/* Disable interrupts to place message in the queue. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_PRIORITIZE, queue_ptr, queue_ptr -> tx_queue_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_PRIORITIZE_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Determine if there are fewer than 2 suspended threads. */
|
||||
if (suspended_count < ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if there how many threads are suspended on this queue. */
|
||||
else if (suspended_count == ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Pickup the head pointer and the next pointer. */
|
||||
head_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
next_thread = head_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Determine if the next suspended thread has a higher priority. */
|
||||
if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
|
||||
{
|
||||
|
||||
/* Yes, move the list head to the next thread. */
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the list changed flag to false. */
|
||||
list_changed = TX_FALSE;
|
||||
|
||||
/* Search through the list to find the highest priority thread. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Is the current thread higher priority? */
|
||||
if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, remember that this thread is the highest priority. */
|
||||
priority_thread_ptr = thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if any changes to the list have occurred while
|
||||
interrupts were enabled. */
|
||||
|
||||
/* Is the list head the same? */
|
||||
if (head_ptr != queue_ptr -> tx_queue_suspension_list)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Is the suspended count the same? */
|
||||
if (suspended_count != queue_ptr -> tx_queue_suspended_count)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the list has changed. */
|
||||
if (list_changed == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Move the thread pointer to the next thread. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Save the suspension count and head pointer. */
|
||||
head_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Reset the list changed flag. */
|
||||
list_changed = TX_FALSE;
|
||||
}
|
||||
|
||||
} while (thread_ptr != head_ptr);
|
||||
|
||||
/* Release preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Now determine if the highest priority thread is at the front
|
||||
of the list. */
|
||||
if (priority_thread_ptr != head_ptr)
|
||||
{
|
||||
|
||||
/* No, we need to move the highest priority suspended thread to the
|
||||
front of the list. */
|
||||
|
||||
/* First, remove the highest priority thread by updating the
|
||||
adjacent suspended threads. */
|
||||
next_thread = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Now, link the highest priority thread at the front of the list. */
|
||||
previous_thread = head_ptr -> tx_thread_suspended_previous;
|
||||
priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
|
||||
priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
|
||||
head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
|
||||
|
||||
/* Move the list head pointer to the highest priority suspended thread. */
|
||||
queue_ptr -> tx_queue_suspension_list = priority_thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
/* Return successful status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
486
common/src/tx_queue_receive.c
Normal file
486
common/src/tx_queue_receive.c
Normal file
@ -0,0 +1,486 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_receive PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function receives a message from the specified queue. If there */
|
||||
/* are no messages in the queue, this function waits according to the */
|
||||
/* option specified. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* destination_ptr Pointer to message destination */
|
||||
/* **** MUST BE LARGE ENOUGH TO */
|
||||
/* HOLD MESSAGE **** */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread routine */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_thread_system_suspend Suspend thread routine */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
ULONG *source;
|
||||
ULONG *destination;
|
||||
UINT size;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default the status to TX_SUCCESS. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Disable interrupts to receive message from queue. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total messages received counter. */
|
||||
_tx_queue_performance__messages_received_count++;
|
||||
|
||||
/* Increment the number of messages received from this queue. */
|
||||
queue_ptr -> tx_queue_performance_messages_received_count++;
|
||||
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_RECEIVE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(destination_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_RECEIVE_INSERT
|
||||
|
||||
/* Pickup the thread suspension count. */
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Determine if there is anything in the queue. */
|
||||
if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
|
||||
{
|
||||
|
||||
/* Determine if there are any suspensions. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* There is a message waiting in the queue and there are no suspensi. */
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = queue_ptr -> tx_queue_read;
|
||||
destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Determine if we are at the end. */
|
||||
if (source == queue_ptr -> tx_queue_end)
|
||||
{
|
||||
|
||||
/* Yes, wrap around to the beginning. */
|
||||
source = queue_ptr -> tx_queue_start;
|
||||
}
|
||||
|
||||
/* Setup the queue read pointer. */
|
||||
queue_ptr -> tx_queue_read = source;
|
||||
|
||||
/* Increase the amount of available storage. */
|
||||
queue_ptr -> tx_queue_available_storage++;
|
||||
|
||||
/* Decrease the enqueued count. */
|
||||
queue_ptr -> tx_queue_enqueued--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At this point we know the queue is full. */
|
||||
|
||||
/* Pickup thread suspension list head pointer. */
|
||||
thread_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
|
||||
/* Now determine if there is a queue front suspension active. */
|
||||
|
||||
/* Is the front suspension flag set? */
|
||||
if (thread_ptr -> tx_thread_suspend_option == TX_TRUE)
|
||||
{
|
||||
|
||||
/* Yes, a queue front suspension is present. */
|
||||
|
||||
/* Return the message associated with this suspension. */
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Message is now in the caller's destination. See if this is the only suspended thread
|
||||
on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At this point, we know that the queue is full and there
|
||||
are one or more threads suspended trying to send another
|
||||
message to this queue. */
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = queue_ptr -> tx_queue_read;
|
||||
destination = TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Determine if we are at the end. */
|
||||
if (source == queue_ptr -> tx_queue_end)
|
||||
{
|
||||
|
||||
/* Yes, wrap around to the beginning. */
|
||||
source = queue_ptr -> tx_queue_start;
|
||||
}
|
||||
|
||||
/* Setup the queue read pointer. */
|
||||
queue_ptr -> tx_queue_read = source;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Interrupts are enabled briefly here to keep the interrupt
|
||||
lockout time deterministic. */
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
|
||||
/* Decrement the preemption disable variable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
destination = queue_ptr -> tx_queue_write;
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Determine if we are at the end. */
|
||||
if (destination == queue_ptr -> tx_queue_end)
|
||||
{
|
||||
|
||||
/* Yes, wrap around to the beginning. */
|
||||
destination = queue_ptr -> tx_queue_start;
|
||||
}
|
||||
|
||||
/* Adjust the write pointer. */
|
||||
queue_ptr -> tx_queue_write = destination;
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
thread_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
|
||||
/* Message is now in the queue. See if this is the only suspended thread
|
||||
on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
else if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_QUEUE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total queue empty suspensions counter. */
|
||||
_tx_queue_performance_empty_suspension_count++;
|
||||
|
||||
/* Increment the number of empty suspensions on this queue. */
|
||||
queue_ptr -> tx_queue_performance_empty_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this queue control
|
||||
block and the source pointer. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) destination_ptr;
|
||||
thread_ptr -> tx_thread_suspend_option = TX_FALSE;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = queue_ptr -> tx_queue_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the suspended thread count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_QUEUE_EMPTY;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
426
common/src/tx_queue_send.c
Normal file
426
common/src/tx_queue_send.c
Normal file
@ -0,0 +1,426 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_send PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places a message into the specified queue. If there */
|
||||
/* is no room in the queue, this function waits according to the */
|
||||
/* option specified. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block */
|
||||
/* source_ptr Pointer to message source */
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread routine */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* _tx_thread_system_suspend Suspend thread routine */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
ULONG *source;
|
||||
ULONG *destination;
|
||||
UINT size;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr);
|
||||
#endif
|
||||
|
||||
|
||||
/* Default the status to TX_SUCCESS. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Disable interrupts to place message in the queue. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total messages sent counter. */
|
||||
_tx_queue_performance_messages_sent_count++;
|
||||
|
||||
/* Increment the number of messages sent to this queue. */
|
||||
queue_ptr -> tx_queue_performance_messages_sent_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_QUEUE_SEND_INSERT
|
||||
|
||||
/* Pickup the thread suspension count. */
|
||||
suspended_count = queue_ptr -> tx_queue_suspended_count;
|
||||
|
||||
/* Determine if there is room in the queue. */
|
||||
if (queue_ptr -> tx_queue_available_storage != TX_NO_MESSAGES)
|
||||
{
|
||||
|
||||
/* There is room for the message in the queue. */
|
||||
|
||||
/* Determine if there are suspended on this queue. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No suspended threads, simply place the message in the queue. */
|
||||
|
||||
/* Reduce the amount of available storage. */
|
||||
queue_ptr -> tx_queue_available_storage--;
|
||||
|
||||
/* Increase the enqueued count. */
|
||||
queue_ptr -> tx_queue_enqueued++;
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
|
||||
destination = queue_ptr -> tx_queue_write;
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Determine if we are at the end. */
|
||||
if (destination == queue_ptr -> tx_queue_end)
|
||||
{
|
||||
|
||||
/* Yes, wrap around to the beginning. */
|
||||
destination = queue_ptr -> tx_queue_start;
|
||||
}
|
||||
|
||||
/* Adjust the write pointer. */
|
||||
queue_ptr -> tx_queue_write = destination;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
/* No thread suspended, just return to caller. */
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* There is a thread suspended on an empty queue. Simply
|
||||
copy the message to the suspended thread's destination
|
||||
pointer. */
|
||||
|
||||
/* Pickup the head of the suspension list. */
|
||||
thread_ptr = queue_ptr -> tx_queue_suspension_list;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
queue_ptr -> tx_queue_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Setup source and destination pointers. */
|
||||
source = TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
|
||||
destination = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
|
||||
size = queue_ptr -> tx_queue_message_size;
|
||||
|
||||
/* Copy message. Note that the source and destination pointers are
|
||||
incremented by the macro. */
|
||||
TX_QUEUE_MESSAGE_COPY(source, destination, size)
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point, the queue is full. Determine if suspension is requested. */
|
||||
else if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_QUEUE_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Yes, prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total number of queue full suspensions. */
|
||||
_tx_queue_performance_full_suspension_count++;
|
||||
|
||||
/* Increment the number of full suspensions on this queue. */
|
||||
queue_ptr -> tx_queue_performance_full_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_queue_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this queue control
|
||||
block and the source pointer. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) queue_ptr;
|
||||
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) source_ptr;
|
||||
thread_ptr -> tx_thread_suspend_option = TX_FALSE;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
queue_ptr -> tx_queue_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = queue_ptr -> tx_queue_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the suspended thread count. */
|
||||
queue_ptr -> tx_queue_suspended_count = suspended_count + ((UINT) 1);
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_QUEUE_SUSP;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the notify callback routine for this queue. */
|
||||
queue_send_notify = queue_ptr -> tx_queue_send_notify;
|
||||
#endif
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if a notify callback is required. */
|
||||
if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Determine if there is a notify callback. */
|
||||
if (queue_send_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Call application queue send notification. */
|
||||
(queue_send_notify)(queue_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Otherwise, just return a queue full error message to the caller. */
|
||||
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the number of full non-suspensions on this queue. */
|
||||
queue_ptr -> tx_queue_performance_full_error_count++;
|
||||
|
||||
/* Increment the total number of full non-suspensions. */
|
||||
_tx_queue_performance_full_error_count++;
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return error completion. */
|
||||
status = TX_QUEUE_FULL;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
107
common/src/tx_queue_send_notify.c
Normal file
107
common/src/tx_queue_send_notify.c
Normal file
@ -0,0 +1,107 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Queue */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_queue.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_queue_send_notify PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application callback function that is */
|
||||
/* called whenever a messages is sent to this queue. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* queue_ptr Pointer to queue control block*/
|
||||
/* queue_send_notify Application callback function */
|
||||
/* (TX_NULL disables notify) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr))
|
||||
{
|
||||
|
||||
#ifdef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
TX_QUEUE_NOT_USED(queue_ptr);
|
||||
TX_QUEUE_SEND_NOTIFY_NOT_USED(queue_send_notify);
|
||||
|
||||
/* Feature is not enabled, return error. */
|
||||
return(TX_FEATURE_NOT_ENABLED);
|
||||
#else
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND_NOTIFY, queue_ptr, 0, 0, 0, TX_TRACE_QUEUE_EVENTS)
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_EL_QUEUE_SEND_NOTIFY_INSERT
|
||||
|
||||
/* Setup queue send notification callback function. */
|
||||
queue_ptr -> tx_queue_send_notify = queue_send_notify;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success to caller. */
|
||||
return(TX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
243
common/src/tx_semaphore_ceiling_put.c
Normal file
243
common/src/tx_semaphore_ceiling_put.c
Normal file
@ -0,0 +1,243 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_ceiling_put PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function puts an instance into the specified counting */
|
||||
/* semaphore up to the specified semaphore ceiling. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore */
|
||||
/* ceiling Maximum value of semaphore */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume */
|
||||
/* thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr);
|
||||
#endif
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default the status to TX_SUCCESS. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Disable interrupts to put an instance back to the semaphore. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total semaphore put counter. */
|
||||
_tx_semaphore_performance_put_count++;
|
||||
|
||||
/* Increment the number of puts on this semaphore. */
|
||||
semaphore_ptr -> tx_semaphore_performance_put_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CEILING_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, ceiling, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_CEILING_PUT_INSERT
|
||||
|
||||
/* Pickup the number of suspended threads. */
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
|
||||
/* Determine if there are any threads suspended on the semaphore. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Determine if the ceiling has been exceeded. */
|
||||
if (semaphore_ptr -> tx_semaphore_count >= ceiling)
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return an error. */
|
||||
status = TX_CEILING_EXCEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the semaphore count. */
|
||||
semaphore_ptr -> tx_semaphore_count++;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the application notify function. */
|
||||
semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if notification is required. */
|
||||
if (semaphore_put_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, call the appropriate notify callback function. */
|
||||
(semaphore_put_notify)(semaphore_ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return successful completion status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* Pickup the pointer to the first suspended thread. */
|
||||
thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
semaphore_ptr -> tx_semaphore_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the application notify function. */
|
||||
semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
|
||||
#endif
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if notification is required. */
|
||||
if (semaphore_put_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, call the appropriate notify callback function. */
|
||||
(semaphore_put_notify)(semaphore_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return successful completion. */
|
||||
return(status);
|
||||
}
|
||||
|
215
common/src/tx_semaphore_cleanup.c
Normal file
215
common/src/tx_semaphore_cleanup.c
Normal file
@ -0,0 +1,215 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_cleanup PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes semaphore timeout and thread terminate */
|
||||
/* actions that require the semaphore data structures to be cleaned */
|
||||
/* up. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to suspended thread's */
|
||||
/* control block */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_timeout Thread timeout processing */
|
||||
/* _tx_thread_terminate Thread terminate processing */
|
||||
/* _tx_thread_wait_abort Thread wait abort processing */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_semaphore_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
|
||||
{
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
#endif
|
||||
|
||||
TX_SEMAPHORE *semaphore_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Disable interrupts to remove the suspended thread from the semaphore. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if the cleanup is still required. */
|
||||
if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_semaphore_cleanup))
|
||||
{
|
||||
|
||||
/* Check for valid suspension sequence. */
|
||||
if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
|
||||
{
|
||||
|
||||
/* Setup pointer to semaphore control block. */
|
||||
semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
|
||||
/* Check for a NULL semaphore pointer. */
|
||||
if (semaphore_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Check for a valid semaphore ID. */
|
||||
if (semaphore_ptr -> tx_semaphore_id == TX_SEMAPHORE_ID)
|
||||
{
|
||||
|
||||
/* Determine if there are any thread suspensions. */
|
||||
if (semaphore_ptr -> tx_semaphore_suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
#else
|
||||
|
||||
/* Setup pointer to semaphore control block. */
|
||||
semaphore_ptr = TX_VOID_TO_SEMAPHORE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
|
||||
#endif
|
||||
|
||||
/* Yes, we still have thread suspension! */
|
||||
|
||||
/* Clear the suspension cleanup flag. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Decrement the suspended count. */
|
||||
semaphore_ptr -> tx_semaphore_suspended_count--;
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same suspension list. */
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Determine if we need to update the head pointer. */
|
||||
if (semaphore_ptr -> tx_semaphore_suspension_list == thread_ptr)
|
||||
{
|
||||
|
||||
/* Update the list head pointer. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we need to determine if this cleanup is from a terminate, timeout,
|
||||
or from a wait abort. */
|
||||
if (thread_ptr -> tx_thread_state == TX_SEMAPHORE_SUSP)
|
||||
{
|
||||
|
||||
/* Timeout condition and the thread is still suspended on the semaphore.
|
||||
Setup return error status and resume the thread. */
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total timeouts counter. */
|
||||
_tx_semaphore_performance_timeout_count++;
|
||||
|
||||
/* Increment the number of timeouts on this semaphore. */
|
||||
semaphore_ptr -> tx_semaphore_performance_timeout_count++;
|
||||
#endif
|
||||
|
||||
/* Setup return status. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_NO_INSTANCE;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
#endif
|
||||
}
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#endif
|
||||
}
|
||||
|
142
common/src/tx_semaphore_create.c
Normal file
142
common/src/tx_semaphore_create.c
Normal file
@ -0,0 +1,142 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a counting semaphore with the initial count */
|
||||
/* specified in this call. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* name_ptr Pointer to semaphore name */
|
||||
/* initial_count Initial semaphore count */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_SEMAPHORE *next_semaphore;
|
||||
TX_SEMAPHORE *previous_semaphore;
|
||||
|
||||
|
||||
/* Initialize semaphore control block to all zeros. */
|
||||
TX_MEMSET(semaphore_ptr, 0, (sizeof(TX_SEMAPHORE)));
|
||||
|
||||
/* Setup the basic semaphore fields. */
|
||||
semaphore_ptr -> tx_semaphore_name = name_ptr;
|
||||
semaphore_ptr -> tx_semaphore_count = initial_count;
|
||||
|
||||
/* Disable interrupts to place the semaphore on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Setup the semaphore ID to make it valid. */
|
||||
semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID;
|
||||
|
||||
/* Place the semaphore on the list of created semaphores. First,
|
||||
check for an empty list. */
|
||||
if (_tx_semaphore_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created semaphore list is empty. Add semaphore to empty list. */
|
||||
_tx_semaphore_created_ptr = semaphore_ptr;
|
||||
semaphore_ptr -> tx_semaphore_created_next = semaphore_ptr;
|
||||
semaphore_ptr -> tx_semaphore_created_previous = semaphore_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_semaphore = _tx_semaphore_created_ptr;
|
||||
previous_semaphore = next_semaphore -> tx_semaphore_created_previous;
|
||||
|
||||
/* Place the new semaphore in the list. */
|
||||
next_semaphore -> tx_semaphore_created_previous = semaphore_ptr;
|
||||
previous_semaphore -> tx_semaphore_created_next = semaphore_ptr;
|
||||
|
||||
/* Setup this semaphore's next and previous created links. */
|
||||
semaphore_ptr -> tx_semaphore_created_previous = previous_semaphore;
|
||||
semaphore_ptr -> tx_semaphore_created_next = next_semaphore;
|
||||
}
|
||||
|
||||
/* Increment the created count. */
|
||||
_tx_semaphore_created_count++;
|
||||
|
||||
/* Optional semaphore create extended processing. */
|
||||
TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_SEMAPHORE, semaphore_ptr, name_ptr, initial_count, 0)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_CREATE, semaphore_ptr, initial_count, TX_POINTER_TO_ULONG_CONVERT(&next_semaphore), 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_CREATE_INSERT
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
207
common/src/tx_semaphore_delete.c
Normal file
207
common/src/tx_semaphore_delete.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function deletes the specified semaphore. All threads */
|
||||
/* suspended on the semaphore are resumed with the TX_DELETED status */
|
||||
/* code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Successful completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
UINT suspended_count;
|
||||
TX_SEMAPHORE *next_semaphore;
|
||||
TX_SEMAPHORE *previous_semaphore;
|
||||
|
||||
|
||||
/* Disable interrupts to remove the semaphore from the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_DELETE, semaphore_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Optional semaphore delete extended processing. */
|
||||
TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(semaphore_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_DELETE_INSERT
|
||||
|
||||
/* Clear the semaphore ID to make it invalid. */
|
||||
semaphore_ptr -> tx_semaphore_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of semaphores. */
|
||||
_tx_semaphore_created_count--;
|
||||
|
||||
/* See if the semaphore is the only one on the list. */
|
||||
if (_tx_semaphore_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created semaphore, just set the created list to NULL. */
|
||||
_tx_semaphore_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Link-up the neighbors. */
|
||||
next_semaphore = semaphore_ptr -> tx_semaphore_created_next;
|
||||
previous_semaphore = semaphore_ptr -> tx_semaphore_created_previous;
|
||||
next_semaphore -> tx_semaphore_created_previous = previous_semaphore;
|
||||
previous_semaphore -> tx_semaphore_created_next = next_semaphore;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_semaphore_created_ptr == semaphore_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_semaphore_created_ptr = next_semaphore;
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Pickup the suspension information. */
|
||||
thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
semaphore_ptr -> tx_semaphore_suspended_count = TX_NO_SUSPENSIONS;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Walk through the semaphore list to resume any and all threads suspended
|
||||
on this semaphore. */
|
||||
while (suspended_count != TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
suspended_count--;
|
||||
|
||||
/* Lockout interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Clear the cleanup pointer, this prevents the timeout from doing
|
||||
anything. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
/* Set the return status in the thread to TX_DELETED. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_DELETED;
|
||||
|
||||
/* Move the thread pointer ahead. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption again. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume the thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Move to next thread. */
|
||||
thread_ptr = next_thread;
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_SEMAPHORE_DELETE_PORT_COMPLETION(semaphore_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Release previous preempt disable. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Return TX_SUCCESS. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
232
common/src/tx_semaphore_get.c
Normal file
232
common/src/tx_semaphore_get.c
Normal file
@ -0,0 +1,232 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets an instance from the specified counting */
|
||||
/* semaphore. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* wait_option Suspension option */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_suspend Suspend thread service */
|
||||
/* _tx_thread_system_ni_suspend Non-interruptable suspend thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default the status to TX_SUCCESS. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Disable interrupts to get an instance from the semaphore. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total semaphore get counter. */
|
||||
_tx_semaphore_performance_get_count++;
|
||||
|
||||
/* Increment the number of attempts to get this semaphore. */
|
||||
semaphore_ptr -> tx_semaphore_performance_get_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_GET, semaphore_ptr, wait_option, semaphore_ptr -> tx_semaphore_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_GET_INSERT
|
||||
|
||||
/* Determine if there is an instance of the semaphore. */
|
||||
if (semaphore_ptr -> tx_semaphore_count != ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Decrement the semaphore count. */
|
||||
semaphore_ptr -> tx_semaphore_count--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if the request specifies suspension. */
|
||||
else if (wait_option != TX_NO_WAIT)
|
||||
{
|
||||
|
||||
/* Determine if the preempt disable flag is non-zero. */
|
||||
if (_tx_thread_preempt_disable != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
|
||||
status = TX_NO_INSTANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Prepare for suspension of this thread. */
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total semaphore suspensions counter. */
|
||||
_tx_semaphore_performance_suspension_count++;
|
||||
|
||||
/* Increment the number of suspensions on this semaphore. */
|
||||
semaphore_ptr -> tx_semaphore_performance_suspension_count++;
|
||||
#endif
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Setup cleanup routine pointer. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_semaphore_cleanup);
|
||||
|
||||
/* Setup cleanup information, i.e. this semaphore control
|
||||
block. */
|
||||
thread_ptr -> tx_thread_suspend_control_block = (VOID *) semaphore_ptr;
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Increment the suspension sequence number, which is used to identify
|
||||
this suspension event. */
|
||||
thread_ptr -> tx_thread_suspension_sequence++;
|
||||
#endif
|
||||
|
||||
/* Setup suspension list. */
|
||||
if (semaphore_ptr -> tx_semaphore_suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* No other threads are suspended. Setup the head pointer and
|
||||
just setup this threads pointers to itself. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add current thread to the end. */
|
||||
next_thread = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
thread_ptr -> tx_thread_suspended_next = next_thread;
|
||||
previous_thread = next_thread -> tx_thread_suspended_previous;
|
||||
thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = thread_ptr;
|
||||
next_thread -> tx_thread_suspended_previous = thread_ptr;
|
||||
}
|
||||
|
||||
/* Increment the number of suspensions. */
|
||||
semaphore_ptr -> tx_semaphore_suspended_count++;
|
||||
|
||||
/* Set the state to suspended. */
|
||||
thread_ptr -> tx_thread_state = TX_SEMAPHORE_SUSP;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Call actual non-interruptable thread suspension routine. */
|
||||
_tx_thread_system_ni_suspend(thread_ptr, wait_option);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Set the suspending flag. */
|
||||
thread_ptr -> tx_thread_suspending = TX_TRUE;
|
||||
|
||||
/* Setup the timeout period. */
|
||||
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_tx_thread_system_suspend(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Return the completion status. */
|
||||
status = thread_ptr -> tx_thread_suspend_status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Immediate return, return error completion. */
|
||||
status = TX_NO_INSTANCE;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
139
common/src/tx_semaphore_info_get.c
Normal file
139
common/src/tx_semaphore_info_get.c
Normal file
@ -0,0 +1,139 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified semaphore. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* name Destination for the semaphore name*/
|
||||
/* current_value Destination for current value of */
|
||||
/* the semaphore */
|
||||
/* first_suspended Destination for pointer of first */
|
||||
/* thread suspended on semaphore */
|
||||
/* suspended_count Destination for suspended count */
|
||||
/* next_semaphore Destination for pointer to next */
|
||||
/* semaphore on the created list */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value,
|
||||
TX_THREAD **first_suspended, ULONG *suspended_count,
|
||||
TX_SEMAPHORE **next_semaphore)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the semaphore. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = semaphore_ptr -> tx_semaphore_name;
|
||||
}
|
||||
|
||||
/* Retrieve the current value of the semaphore. */
|
||||
if (current_value != TX_NULL)
|
||||
{
|
||||
|
||||
*current_value = semaphore_ptr -> tx_semaphore_count;
|
||||
}
|
||||
|
||||
/* Retrieve the first thread suspended on this semaphore. */
|
||||
if (first_suspended != TX_NULL)
|
||||
{
|
||||
|
||||
*first_suspended = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
}
|
||||
|
||||
/* Retrieve the number of threads suspended on this semaphore. */
|
||||
if (suspended_count != TX_NULL)
|
||||
{
|
||||
|
||||
*suspended_count = (ULONG) semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to the next semaphore created. */
|
||||
if (next_semaphore != TX_NULL)
|
||||
{
|
||||
|
||||
*next_semaphore = semaphore_ptr -> tx_semaphore_created_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
129
common/src/tx_semaphore_initialize.c
Normal file
129
common/src/tx_semaphore_initialize.c
Normal file
@ -0,0 +1,129 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
#ifndef TX_INLINE_INITIALIZATION
|
||||
|
||||
/* Locate semaphore component data in this file. */
|
||||
|
||||
/* Define the head pointer of the created semaphore list. */
|
||||
|
||||
TX_SEMAPHORE * _tx_semaphore_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created semaphores. */
|
||||
|
||||
ULONG _tx_semaphore_created_count;
|
||||
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of semaphore puts. */
|
||||
|
||||
ULONG _tx_semaphore_performance_put_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore gets. */
|
||||
|
||||
ULONG _tx_semaphore_performance_get_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore suspensions. */
|
||||
|
||||
ULONG _tx_semaphore_performance_suspension_count;
|
||||
|
||||
|
||||
/* Define the total number of semaphore timeouts. */
|
||||
|
||||
ULONG _tx_semaphore_performance_timeout_count;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the semaphore component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_semaphore_initialize(VOID)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the head pointer of the created semaphores list and the
|
||||
number of semaphores created. */
|
||||
_tx_semaphore_created_ptr = TX_NULL;
|
||||
_tx_semaphore_created_count = TX_EMPTY;
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Initialize semaphore performance counters. */
|
||||
_tx_semaphore_performance_put_count = ((ULONG) 0);
|
||||
_tx_semaphore_performance_get_count = ((ULONG) 0);
|
||||
_tx_semaphore_performance_suspension_count = ((ULONG) 0);
|
||||
_tx_semaphore_performance_timeout_count = ((ULONG) 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
201
common/src/tx_semaphore_performance_info_get.c
Normal file
201
common/src/tx_semaphore_performance_info_get.c
Normal file
@ -0,0 +1,201 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_semaphore.h"
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* semaphore. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* puts Destination for the number of */
|
||||
/* puts on to this semaphore */
|
||||
/* gets Destination for the number of */
|
||||
/* gets on this semaphore */
|
||||
/* suspensions Destination for the number of */
|
||||
/* suspensions on this semaphore */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* on this semaphore */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets,
|
||||
ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (semaphore_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Semaphore pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the semaphore ID is invalid. */
|
||||
else if (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)
|
||||
{
|
||||
|
||||
/* Semaphore pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PERFORMANCE_INFO_GET, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the number of puts on this semaphore. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
*puts = semaphore_ptr -> tx_semaphore_performance_put_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of gets on this semaphore. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = semaphore_ptr -> tx_semaphore_performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of suspensions on this semaphore. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = semaphore_ptr -> tx_semaphore_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the number of timeouts on this semaphore. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = semaphore_ptr -> tx_semaphore_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return successful completion. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (semaphore_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
174
common/src/tx_semaphore_performance_system_info_get.c
Normal file
174
common/src/tx_semaphore_performance_system_info_get.c
Normal file
@ -0,0 +1,174 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_semaphore.h"
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves system semaphore performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* puts Destination for total number of */
|
||||
/* semaphore puts */
|
||||
/* gets Destination for total number of */
|
||||
/* semaphore gets */
|
||||
/* suspensions Destination for total number of */
|
||||
/* semaphore suspensions */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_performance_system_info_get(ULONG *puts, ULONG *gets, ULONG *suspensions, ULONG *timeouts)
|
||||
{
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE__PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the total number of semaphore puts. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
*puts = _tx_semaphore_performance_put_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of semaphore gets. */
|
||||
if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
*gets = _tx_semaphore_performance_get_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of semaphore suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_semaphore_performance_suspension_count;
|
||||
}
|
||||
|
||||
/* Retrieve the total number of semaphore timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_semaphore_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (puts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (gets != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
251
common/src/tx_semaphore_prioritize.c
Normal file
251
common/src/tx_semaphore_prioritize.c
Normal file
@ -0,0 +1,251 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_prioritize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function places the highest priority suspended thread at the */
|
||||
/* front of the suspension list. All other threads remain in the same */
|
||||
/* FIFO suspension order. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
TX_THREAD *priority_thread_ptr;
|
||||
TX_THREAD *head_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT list_changed;
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PRIORITIZE, semaphore_ptr, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_PRIORITIZE_INSERT
|
||||
|
||||
/* Pickup the suspended count. */
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
|
||||
/* Determine if there are fewer than 2 suspended threads. */
|
||||
if (suspended_count < ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Determine if there how many threads are suspended on this semaphore. */
|
||||
else if (suspended_count == ((UINT) 2))
|
||||
{
|
||||
|
||||
/* Pickup the head pointer and the next pointer. */
|
||||
head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
next_thread = head_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Determine if the next suspended thread has a higher priority. */
|
||||
if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
|
||||
{
|
||||
|
||||
/* Yes, move the list head to the next thread. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Remember the suspension count and head pointer. */
|
||||
head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Set the list changed flag to false. */
|
||||
list_changed = TX_FALSE;
|
||||
|
||||
/* Search through the list to find the highest priority thread. */
|
||||
do
|
||||
{
|
||||
|
||||
/* Is the current thread higher priority? */
|
||||
if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Yes, remember that this thread is the highest priority. */
|
||||
priority_thread_ptr = thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts temporarily. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Disable interrupts again. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Determine if any changes to the list have occurred while
|
||||
interrupts were enabled. */
|
||||
|
||||
/* Is the list head the same? */
|
||||
if (head_ptr != semaphore_ptr -> tx_semaphore_suspension_list)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Is the suspended count the same? */
|
||||
if (suspended_count != semaphore_ptr -> tx_semaphore_suspended_count)
|
||||
{
|
||||
|
||||
/* The list head has changed, set the list changed flag. */
|
||||
list_changed = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the list has changed. */
|
||||
if (list_changed == TX_FALSE)
|
||||
{
|
||||
|
||||
/* Yes, everything is the same... move the thread pointer to the next thread. */
|
||||
thread_ptr = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No, the list is been modified so we need to start the search over. */
|
||||
|
||||
/* Save the suspension count and head pointer. */
|
||||
head_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
|
||||
/* Default the highest priority thread to the thread at the front of the list. */
|
||||
priority_thread_ptr = head_ptr;
|
||||
|
||||
/* Setup search pointer. */
|
||||
thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
|
||||
/* Reset the list changed flag. */
|
||||
list_changed = TX_FALSE;
|
||||
}
|
||||
|
||||
} while (thread_ptr != head_ptr);
|
||||
|
||||
/* Release preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Now determine if the highest priority thread is at the front
|
||||
of the list. */
|
||||
if (priority_thread_ptr != head_ptr)
|
||||
{
|
||||
|
||||
/* No, we need to move the highest priority suspended thread to the
|
||||
front of the list. */
|
||||
|
||||
/* First, remove the highest priority thread by updating the
|
||||
adjacent suspended threads. */
|
||||
next_thread = priority_thread_ptr -> tx_thread_suspended_next;
|
||||
previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
|
||||
/* Now, link the highest priority thread at the front of the list. */
|
||||
previous_thread = head_ptr -> tx_thread_suspended_previous;
|
||||
priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
|
||||
priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
|
||||
head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
|
||||
|
||||
/* Move the list head pointer to the highest priority suspended thread. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = priority_thread_ptr;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
222
common/src/tx_semaphore_put.c
Normal file
222
common/src/tx_semaphore_put.c
Normal file
@ -0,0 +1,222 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_put PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function puts an instance into the specified counting */
|
||||
/* semaphore. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore control block*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_SUCCESS Success completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_resume Resume thread service */
|
||||
/* _tx_thread_system_ni_resume Non-interruptable resume thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*semaphore_put_notify)(struct TX_SEMAPHORE_STRUCT *notify_semaphore_ptr);
|
||||
#endif
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
UINT suspended_count;
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
|
||||
|
||||
/* Disable interrupts to put an instance back to the semaphore. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Increment the total semaphore put counter. */
|
||||
_tx_semaphore_performance_put_count++;
|
||||
|
||||
/* Increment the number of puts on this semaphore. */
|
||||
semaphore_ptr -> tx_semaphore_performance_put_count++;
|
||||
#endif
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT, semaphore_ptr, semaphore_ptr -> tx_semaphore_count, semaphore_ptr -> tx_semaphore_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_SEMAPHORE_PUT_INSERT
|
||||
|
||||
/* Pickup the number of suspended threads. */
|
||||
suspended_count = semaphore_ptr -> tx_semaphore_suspended_count;
|
||||
|
||||
/* Determine if there are any threads suspended on the semaphore. */
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Increment the semaphore count. */
|
||||
semaphore_ptr -> tx_semaphore_count++;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the application notify function. */
|
||||
semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
|
||||
#endif
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if notification is required. */
|
||||
if (semaphore_put_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, call the appropriate notify callback function. */
|
||||
(semaphore_put_notify)(semaphore_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* A thread is suspended on this semaphore. */
|
||||
|
||||
/* Pickup the pointer to the first suspended thread. */
|
||||
thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
|
||||
|
||||
/* Remove the suspended thread from the list. */
|
||||
|
||||
/* See if this is the only suspended thread on the list. */
|
||||
suspended_count--;
|
||||
if (suspended_count == TX_NO_SUSPENSIONS)
|
||||
{
|
||||
|
||||
/* Yes, the only suspended thread. */
|
||||
|
||||
/* Update the head pointer. */
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* At least one more thread is on the same expiration list. */
|
||||
|
||||
/* Update the list head pointer. */
|
||||
next_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
semaphore_ptr -> tx_semaphore_suspension_list = next_thread;
|
||||
|
||||
/* Update the links of the adjacent threads. */
|
||||
previous_thread = thread_ptr -> tx_thread_suspended_previous;
|
||||
next_thread -> tx_thread_suspended_previous = previous_thread;
|
||||
previous_thread -> tx_thread_suspended_next = next_thread;
|
||||
}
|
||||
|
||||
/* Decrement the suspension count. */
|
||||
semaphore_ptr -> tx_semaphore_suspended_count = suspended_count;
|
||||
|
||||
/* Prepare for resumption of the first thread. */
|
||||
|
||||
/* Clear cleanup routine to avoid timeout. */
|
||||
thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the application notify function. */
|
||||
semaphore_put_notify = semaphore_ptr -> tx_semaphore_put_notify;
|
||||
#endif
|
||||
|
||||
/* Put return status into the thread control block. */
|
||||
thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Resume thread. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Determine if notification is required. */
|
||||
if (semaphore_put_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, call the appropriate notify callback function. */
|
||||
(semaphore_put_notify)(semaphore_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return successful completion. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
107
common/src/tx_semaphore_put_notify.c
Normal file
107
common/src/tx_semaphore_put_notify.c
Normal file
@ -0,0 +1,107 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Semaphore */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_semaphore.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_semaphore_put_notify PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application callback function that is */
|
||||
/* called whenever the this semaphore is put. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* semaphore_ptr Pointer to semaphore */
|
||||
/* semaphore_put_notify Application callback function */
|
||||
/* (TX_NULL disables notify) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Service return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr))
|
||||
{
|
||||
|
||||
#ifdef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
TX_SEMAPHORE_NOT_USED(semaphore_ptr);
|
||||
TX_SEMAPHORE_PUT_NOTIFY_NOT_USED(semaphore_put_notify);
|
||||
|
||||
/* Feature is not enabled, return error. */
|
||||
return(TX_FEATURE_NOT_ENABLED);
|
||||
#else
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_SEMAPHORE_PUT_NOTIFY, semaphore_ptr, 0, 0, 0, TX_TRACE_SEMAPHORE_EVENTS)
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_EL_SEMAPHORE_PUT_NOTIFY_INSERT
|
||||
|
||||
/* Setup semaphore put notification callback function. */
|
||||
semaphore_ptr -> tx_semaphore_put_notify = semaphore_put_notify;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success to caller. */
|
||||
return(TX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
360
common/src/tx_thread_create.c
Normal file
360
common/src/tx_thread_create.c
Normal file
@ -0,0 +1,360 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_initialize.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_create PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function creates a thread and places it on the list of created */
|
||||
/* threads. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Thread control block pointer */
|
||||
/* name Pointer to thread name string */
|
||||
/* entry_function Entry function of the thread */
|
||||
/* entry_input 32-bit input value to thread */
|
||||
/* stack_start Pointer to start of stack */
|
||||
/* stack_size Stack size in bytes */
|
||||
/* priority Priority of thread */
|
||||
/* (default 0-31) */
|
||||
/* preempt_threshold Preemption threshold */
|
||||
/* time_slice Thread time-slice value */
|
||||
/* auto_start Automatic start selection */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* return status Thread create return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Build initial thread stack */
|
||||
/* _tx_thread_system_resume Resume automatic start thread */
|
||||
/* _tx_thread_system_ni_resume Noninterruptable resume thread*/
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* _tx_timer_initialize Create system timer thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input,
|
||||
VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold,
|
||||
ULONG time_slice, UINT auto_start)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
TX_THREAD *saved_thread_ptr;
|
||||
UINT saved_threshold = ((UINT) 0);
|
||||
UCHAR *temp_ptr;
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
ULONG new_stack_start;
|
||||
ULONG updated_stack_start;
|
||||
#endif
|
||||
|
||||
#ifndef TX_DISABLE_STACK_FILLING
|
||||
|
||||
/* Set the thread stack to a pattern prior to creating the initial
|
||||
stack frame. This pattern is used by the stack checking routines
|
||||
to see how much has been used. */
|
||||
TX_MEMSET(stack_start, ((UCHAR) TX_STACK_FILL), stack_size);
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
|
||||
/* Ensure that there are two ULONG of 0xEF patterns at the top and
|
||||
bottom of the thread's stack. This will be used to check for stack
|
||||
overflow conditions during run-time. */
|
||||
stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG));
|
||||
|
||||
/* Ensure the starting stack address is evenly aligned. */
|
||||
new_stack_start = TX_POINTER_TO_ULONG_CONVERT(stack_start);
|
||||
updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1))));
|
||||
|
||||
/* Determine if the starting stack address is different. */
|
||||
if (new_stack_start != updated_stack_start)
|
||||
{
|
||||
|
||||
/* Yes, subtract another ULONG from the size to avoid going past the stack area. */
|
||||
stack_size = stack_size - (sizeof(ULONG));
|
||||
}
|
||||
|
||||
/* Update the starting stack pointer. */
|
||||
stack_start = TX_ULONG_TO_POINTER_CONVERT(updated_stack_start);
|
||||
#endif
|
||||
|
||||
/* Prepare the thread control block prior to placing it on the created
|
||||
list. */
|
||||
|
||||
/* Initialize thread control block to all zeros. */
|
||||
TX_MEMSET(thread_ptr, 0, (sizeof(TX_THREAD)));
|
||||
|
||||
/* Place the supplied parameters into the thread's control block. */
|
||||
thread_ptr -> tx_thread_name = name_ptr;
|
||||
thread_ptr -> tx_thread_entry = entry_function;
|
||||
thread_ptr -> tx_thread_entry_parameter = entry_input;
|
||||
thread_ptr -> tx_thread_stack_start = stack_start;
|
||||
thread_ptr -> tx_thread_stack_size = stack_size;
|
||||
thread_ptr -> tx_thread_priority = priority;
|
||||
thread_ptr -> tx_thread_user_priority = priority;
|
||||
thread_ptr -> tx_thread_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_new_time_slice = time_slice;
|
||||
thread_ptr -> tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES);
|
||||
|
||||
/* Calculate the end of the thread's stack area. */
|
||||
temp_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(stack_start);
|
||||
temp_ptr = (TX_UCHAR_POINTER_ADD(temp_ptr, (stack_size - ((ULONG) 1))));
|
||||
thread_ptr -> tx_thread_stack_end = TX_UCHAR_TO_VOID_POINTER_CONVERT(temp_ptr);
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Preemption-threshold is enabled, setup accordingly. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = preempt_threshold;
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = preempt_threshold;
|
||||
#else
|
||||
|
||||
/* Preemption-threshold is disabled, determine if preemption-threshold was required. */
|
||||
if (priority != preempt_threshold)
|
||||
{
|
||||
|
||||
/* Preemption-threshold specified. Since specific preemption-threshold is not supported,
|
||||
disable all preemption. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = ((UINT) 0);
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = ((UINT) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Preemption-threshold is not specified, just setup with the priority. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = priority;
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = priority;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now fill in the values that are required for thread initialization. */
|
||||
thread_ptr -> tx_thread_state = TX_SUSPENDED;
|
||||
|
||||
/* Setup the necessary fields in the thread timer block. */
|
||||
TX_THREAD_CREATE_TIMEOUT_SETUP(thread_ptr)
|
||||
|
||||
/* Perform any additional thread setup activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_INTERNAL_EXTENSION(thread_ptr)
|
||||
|
||||
/* Call the target specific stack frame building routine to build the
|
||||
thread's initial stack and to setup the actual stack pointer in the
|
||||
control block. */
|
||||
_tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry);
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
|
||||
/* Setup the highest usage stack pointer. */
|
||||
thread_ptr -> tx_thread_stack_highest_ptr = thread_ptr -> tx_thread_stack_ptr;
|
||||
#endif
|
||||
|
||||
/* Prepare to make this thread a member of the created thread list. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Load the thread ID field in the thread control block. */
|
||||
thread_ptr -> tx_thread_id = TX_THREAD_ID;
|
||||
|
||||
/* Place the thread on the list of created threads. First,
|
||||
check for an empty list. */
|
||||
if (_tx_thread_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* The created thread list is empty. Add thread to empty list. */
|
||||
_tx_thread_created_ptr = thread_ptr;
|
||||
thread_ptr -> tx_thread_created_next = thread_ptr;
|
||||
thread_ptr -> tx_thread_created_previous = thread_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* This list is not NULL, add to the end of the list. */
|
||||
next_thread = _tx_thread_created_ptr;
|
||||
previous_thread = next_thread -> tx_thread_created_previous;
|
||||
|
||||
/* Place the new thread in the list. */
|
||||
next_thread -> tx_thread_created_previous = thread_ptr;
|
||||
previous_thread -> tx_thread_created_next = thread_ptr;
|
||||
|
||||
/* Setup this thread's created links. */
|
||||
thread_ptr -> tx_thread_created_previous = previous_thread;
|
||||
thread_ptr -> tx_thread_created_next = next_thread;
|
||||
}
|
||||
|
||||
/* Increment the thread created count. */
|
||||
_tx_thread_created_count++;
|
||||
|
||||
/* If trace is enabled, register this object. */
|
||||
TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_THREAD, thread_ptr, name_ptr, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_CREATE, thread_ptr, priority, TX_POINTER_TO_ULONG_CONVERT(stack_start), stack_size, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Register thread in the thread array structure. */
|
||||
TX_EL_THREAD_REGISTER(thread_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_CREATE_INSERT
|
||||
|
||||
#ifndef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Temporarily disable preemption. */
|
||||
_tx_thread_preempt_disable++;
|
||||
#endif
|
||||
|
||||
/* Determine if an automatic start was requested. If so, call the resume
|
||||
thread function and then check for a preemption condition. */
|
||||
if (auto_start == TX_AUTO_START)
|
||||
{
|
||||
|
||||
/* Determine if the create call is being called from initialization. */
|
||||
if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS)
|
||||
{
|
||||
|
||||
/* Yes, this create call was made from initialization. */
|
||||
|
||||
/* Pickup the current thread execute pointer, which corresponds to the
|
||||
highest priority thread ready to execute. Interrupt lockout is
|
||||
not required, since interrupts are assumed to be disabled during
|
||||
initialization. */
|
||||
saved_thread_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Determine if there is thread ready for execution. */
|
||||
if (saved_thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, a thread is ready for execution when initialization completes. */
|
||||
|
||||
/* Save the current preemption-threshold. */
|
||||
saved_threshold = saved_thread_ptr -> tx_thread_preempt_threshold;
|
||||
|
||||
/* For initialization, temporarily set the preemption-threshold to the
|
||||
priority level to make sure the highest-priority thread runs once
|
||||
initialization is complete. */
|
||||
saved_thread_ptr -> tx_thread_preempt_threshold = saved_thread_ptr -> tx_thread_priority;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Simply set the saved thread pointer to NULL. */
|
||||
saved_thread_ptr = TX_NULL;
|
||||
}
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Resume the thread! */
|
||||
_tx_thread_system_ni_resume(thread_ptr);
|
||||
|
||||
/* Restore previous interrupt posture. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Restore previous interrupt posture. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Call the resume thread function to make this thread ready. */
|
||||
_tx_thread_system_resume(thread_ptr);
|
||||
#endif
|
||||
|
||||
/* Determine if the thread's preemption-threshold needs to be restored. */
|
||||
if (saved_thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, restore the previous highest-priority thread's preemption-threshold. This
|
||||
can only happen if this routine is called from initialization. */
|
||||
saved_thread_ptr -> tx_thread_preempt_threshold = saved_threshold;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
#else
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Re-enable preemption. */
|
||||
_tx_thread_preempt_disable--;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Always return a success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
166
common/src/tx_thread_delete.c
Normal file
166
common/src/tx_thread_delete.c
Normal file
@ -0,0 +1,166 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_delete PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function handles application delete thread requests. The */
|
||||
/* thread to delete must be in a terminated or completed state, */
|
||||
/* otherwise this function just returns an error code. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread to suspend */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Return completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_delete(TX_THREAD *thread_ptr)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
TX_THREAD *next_thread;
|
||||
TX_THREAD *previous_thread;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default status to success. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
/* Lockout interrupts while the thread is being deleted. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Check for proper status of this thread to delete. */
|
||||
if (thread_ptr -> tx_thread_state != TX_COMPLETED)
|
||||
{
|
||||
|
||||
/* Now check for terminated state. */
|
||||
if (thread_ptr -> tx_thread_state != TX_TERMINATED)
|
||||
{
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Thread not completed or terminated - return an error! */
|
||||
status = TX_DELETE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the delete operation is okay. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, continue with deleting the thread. */
|
||||
|
||||
/* Perform any additional activities for tool or user purpose. */
|
||||
TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_DELETE, thread_ptr, TX_POINTER_TO_ULONG_CONVERT(&next_thread), 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* If trace is enabled, unregister this object. */
|
||||
TX_TRACE_OBJECT_UNREGISTER(thread_ptr)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_DELETE_INSERT
|
||||
|
||||
/* Unregister thread in the thread array structure. */
|
||||
TX_EL_THREAD_UNREGISTER(thread_ptr)
|
||||
|
||||
/* Clear the thread ID to make it invalid. */
|
||||
thread_ptr -> tx_thread_id = TX_CLEAR_ID;
|
||||
|
||||
/* Decrement the number of created threads. */
|
||||
_tx_thread_created_count--;
|
||||
|
||||
/* See if the thread is the only one on the list. */
|
||||
if (_tx_thread_created_count == TX_EMPTY)
|
||||
{
|
||||
|
||||
/* Only created thread, just set the created list to NULL. */
|
||||
_tx_thread_created_ptr = TX_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Otherwise, not the only created thread, link-up the neighbors. */
|
||||
next_thread = thread_ptr -> tx_thread_created_next;
|
||||
previous_thread = thread_ptr -> tx_thread_created_previous;
|
||||
next_thread -> tx_thread_created_previous = previous_thread;
|
||||
previous_thread -> tx_thread_created_next = next_thread;
|
||||
|
||||
/* See if we have to update the created list head pointer. */
|
||||
if (_tx_thread_created_ptr == thread_ptr)
|
||||
{
|
||||
|
||||
/* Yes, move the head pointer to the next link. */
|
||||
_tx_thread_created_ptr = next_thread;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
|
||||
TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr)
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
109
common/src/tx_thread_entry_exit_notify.c
Normal file
109
common/src/tx_thread_entry_exit_notify.c
Normal file
@ -0,0 +1,109 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_entry_exit_notify PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application entry/exit notification */
|
||||
/* callback routine for the application. Once registered, the callback */
|
||||
/* routine is called when the thread is initially entered and called */
|
||||
/* again when the thread completes or is terminated. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread */
|
||||
/* thread_entry_exit_notify Pointer to notify callback */
|
||||
/* function, TX_NULL to disable*/
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Service return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id))
|
||||
{
|
||||
|
||||
#ifdef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
TX_THREAD_NOT_USED(thread_ptr);
|
||||
TX_THREAD_ENTRY_EXIT_NOTIFY_NOT_USED(thread_entry_exit_notify);
|
||||
|
||||
/* Feature is not enabled, return error. */
|
||||
return(TX_FEATURE_NOT_ENABLED);
|
||||
#else
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_ENTRY_EXIT_NOTIFY, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Make entry in event log. */
|
||||
TX_EL_THREAD_ENTRY_EXIT_NOTIFY_INSERT
|
||||
|
||||
/* Setup thread entry/exit notification callback function. */
|
||||
thread_ptr -> tx_thread_entry_exit_notify = thread_entry_exit_notify;
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return success to caller. */
|
||||
return(TX_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
103
common/src/tx_thread_identify.c
Normal file
103
common/src/tx_thread_identify.c
Normal file
@ -0,0 +1,103 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_identify PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function returns the control block pointer of the currently */
|
||||
/* executing thread. If the return value is NULL, no thread is */
|
||||
/* executing. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* TX_THREAD * Pointer to control block of */
|
||||
/* currently executing thread */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
TX_THREAD *_tx_thread_identify(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts to put the timer on the created list. */
|
||||
TX_DISABLE
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_IDENTIFY, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
#endif
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_IDENTIFY_INSERT
|
||||
|
||||
/* Pickup thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr)
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return the current thread pointer. */
|
||||
return(thread_ptr);
|
||||
}
|
||||
|
163
common/src/tx_thread_info_get.c
Normal file
163
common/src/tx_thread_info_get.c
Normal file
@ -0,0 +1,163 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves information from the specified thread. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control block */
|
||||
/* name Destination for the thread name */
|
||||
/* state Destination for thread state */
|
||||
/* run_count Destination for thread run count */
|
||||
/* priority Destination for thread priority */
|
||||
/* preemption_threshold Destination for thread preemption-*/
|
||||
/* threshold */
|
||||
/* time_slice Destination for thread time-slice */
|
||||
/* next_thread Destination for next created */
|
||||
/* thread */
|
||||
/* next_suspended_thread Destination for next suspended */
|
||||
/* thread */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count,
|
||||
UINT *priority, UINT *preemption_threshold, ULONG *time_slice,
|
||||
TX_THREAD **next_thread, TX_THREAD **next_suspended_thread)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve the name of the thread. */
|
||||
if (name != TX_NULL)
|
||||
{
|
||||
|
||||
*name = thread_ptr -> tx_thread_name;
|
||||
}
|
||||
|
||||
/* Pickup the thread's current state. */
|
||||
if (state != TX_NULL)
|
||||
{
|
||||
|
||||
*state = thread_ptr -> tx_thread_state;
|
||||
}
|
||||
|
||||
/* Pickup the number of times the thread has been scheduled. */
|
||||
if (run_count != TX_NULL)
|
||||
{
|
||||
|
||||
*run_count = thread_ptr -> tx_thread_run_count;
|
||||
}
|
||||
|
||||
/* Pickup the thread's priority. */
|
||||
if (priority != TX_NULL)
|
||||
{
|
||||
|
||||
*priority = thread_ptr -> tx_thread_user_priority;
|
||||
}
|
||||
|
||||
/* Pickup the thread's preemption-threshold. */
|
||||
if (preemption_threshold != TX_NULL)
|
||||
{
|
||||
|
||||
*preemption_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
|
||||
}
|
||||
|
||||
/* Pickup the thread's current time-slice. */
|
||||
if (time_slice != TX_NULL)
|
||||
{
|
||||
|
||||
*time_slice = thread_ptr -> tx_thread_time_slice;
|
||||
}
|
||||
|
||||
/* Pickup the next created thread. */
|
||||
if (next_thread != TX_NULL)
|
||||
{
|
||||
|
||||
*next_thread = thread_ptr -> tx_thread_created_next;
|
||||
}
|
||||
|
||||
/* Pickup the next thread suspended. */
|
||||
if (next_suspended_thread != TX_NULL)
|
||||
{
|
||||
|
||||
*next_suspended_thread = thread_ptr -> tx_thread_suspended_next;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
448
common/src/tx_thread_initialize.c
Normal file
448
common/src/tx_thread_initialize.c
Normal file
@ -0,0 +1,448 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#define TX_THREAD_INIT
|
||||
#endif
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/* Define the pointer that contains the system stack pointer. This is
|
||||
utilized when control returns from a thread to the system to reset the
|
||||
current stack. This is setup in the low-level initialization function. */
|
||||
|
||||
VOID * _tx_thread_system_stack_ptr;
|
||||
|
||||
|
||||
/* Define the current thread pointer. This variable points to the currently
|
||||
executing thread. If this variable is NULL, no thread is executing. */
|
||||
|
||||
TX_THREAD * _tx_thread_current_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the next thread to execute. It is important
|
||||
to remember that this is not necessarily equal to the current thread
|
||||
pointer. */
|
||||
|
||||
TX_THREAD * _tx_thread_execute_ptr;
|
||||
|
||||
|
||||
/* Define the head pointer of the created thread list. */
|
||||
|
||||
TX_THREAD * _tx_thread_created_ptr;
|
||||
|
||||
|
||||
/* Define the variable that holds the number of created threads. */
|
||||
|
||||
ULONG _tx_thread_created_count;
|
||||
|
||||
|
||||
/* Define the current state variable. When this value is 0, a thread
|
||||
is executing or the system is idle. Other values indicate that
|
||||
interrupt or initialization processing is active. This variable is
|
||||
initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
|
||||
active. */
|
||||
|
||||
volatile ULONG _tx_thread_system_state = TX_INITIALIZE_IN_PROGRESS;
|
||||
|
||||
|
||||
/* Define the 32-bit priority bit-maps. There is one priority bit map for each
|
||||
32 priority levels supported. If only 32 priorities are supported there is
|
||||
only one bit map. Each bit within a priority bit map represents that one
|
||||
or more threads at the associated thread priority are ready. */
|
||||
|
||||
ULONG _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
|
||||
|
||||
|
||||
/* Define the priority map active bit map that specifies which of the previously
|
||||
defined priority maps have something set. This is only necessary if more than
|
||||
32 priorities are supported. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
ULONG _tx_thread_priority_map_active;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Define the 32-bit preempt priority bit maps. There is one preempt bit map
|
||||
for each 32 priority levels supported. If only 32 priorities are supported
|
||||
there is only one bit map. Each set set bit corresponds to a preempted priority
|
||||
level that had preemption-threshold active to protect against preemption of a
|
||||
range of relatively higher priority threads. */
|
||||
|
||||
ULONG _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
|
||||
|
||||
|
||||
/* Define the preempt map active bit map that specifies which of the previously
|
||||
defined preempt maps have something set. This is only necessary if more than
|
||||
32 priorities are supported. */
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
ULONG _tx_thread_preempted_map_active;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define the variable that holds the highest priority group ready for
|
||||
execution. It is important to note that this is not necessarily the same
|
||||
as the priority of the thread pointed to by _tx_execute_thread. */
|
||||
|
||||
UINT _tx_thread_highest_priority;
|
||||
|
||||
|
||||
/* Define the array of thread pointers. Each entry represents the threads that
|
||||
are ready at that priority group. For example, index 10 in this array
|
||||
represents the first thread ready at priority 10. If this entry is NULL,
|
||||
no threads are ready at that priority. */
|
||||
|
||||
TX_THREAD * _tx_thread_priority_list[TX_MAX_PRIORITIES];
|
||||
|
||||
|
||||
/* Define the global preempt disable variable. If this is non-zero, preemption is
|
||||
disabled. It is used internally by ThreadX to prevent preemption of a thread in
|
||||
the middle of a service that is resuming or suspending another thread. */
|
||||
|
||||
volatile UINT _tx_thread_preempt_disable;
|
||||
|
||||
|
||||
/* Define the global function pointer for mutex cleanup on thread completion or
|
||||
termination. This pointer is setup during mutex initialization. */
|
||||
|
||||
VOID (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
|
||||
|
||||
|
||||
/* Define the global build options variable. This contains a bit map representing
|
||||
how the ThreadX library was built. The following are the bit field definitions:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
31 TX_NOT_INTERRUPTABLE defined
|
||||
30 TX_INLINE_THREAD_RESUME_SUSPEND define
|
||||
29-24 Priority groups 1 -> 32 priorities
|
||||
2 -> 64 priorities
|
||||
3 -> 96 priorities
|
||||
|
||||
...
|
||||
|
||||
32 -> 1024 priorities
|
||||
23 TX_TIMER_PROCESS_IN_ISR defined
|
||||
22 TX_REACTIVATE_INLINE defined
|
||||
21 TX_DISABLE_STACK_FILLING defined
|
||||
20 TX_ENABLE_STACK_CHECKING defined
|
||||
19 TX_DISABLE_PREEMPTION_THRESHOLD defined
|
||||
18 TX_DISABLE_REDUNDANT_CLEARING defined
|
||||
17 TX_DISABLE_NOTIFY_CALLBACKS defined
|
||||
16 TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
|
||||
15 TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
|
||||
14 TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
|
||||
13 TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
|
||||
12 TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
|
||||
11 TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
|
||||
10 TX_THREAD_ENABLE_PERFORMANCE_INFO defined
|
||||
9 TX_TIMER_ENABLE_PERFORMANCE_INFO defined
|
||||
8 TX_ENABLE_EVENT_TRACE defined
|
||||
7 TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
|
||||
6-0 Port Specific */
|
||||
|
||||
ULONG _tx_build_options;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
|
||||
/* Define the global function pointer for stack error handling. If a stack error is
|
||||
detected and the application has registered a stack error handler, it will be
|
||||
called via this function pointer. */
|
||||
|
||||
VOID (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Define the total number of thread resumptions. Each time a thread enters the
|
||||
ready state this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_resume_count;
|
||||
|
||||
|
||||
/* Define the total number of thread suspensions. Each time a thread enters a
|
||||
suspended state this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_suspend_count;
|
||||
|
||||
|
||||
/* Define the total number of solicited thread preemptions. Each time a thread is
|
||||
preempted by directly calling a ThreadX service, this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_solicited_preemption_count;
|
||||
|
||||
|
||||
/* Define the total number of interrupt thread preemptions. Each time a thread is
|
||||
preempted as a result of an ISR calling a ThreadX service, this variable is
|
||||
incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_interrupt_preemption_count;
|
||||
|
||||
|
||||
/* Define the total number of priority inversions. Each time a thread is blocked by
|
||||
a mutex owned by a lower-priority thread, this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_priority_inversion_count;
|
||||
|
||||
|
||||
/* Define the total number of time-slices. Each time a time-slice operation is
|
||||
actually performed (another thread is setup for running) this variable is
|
||||
incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_time_slice_count;
|
||||
|
||||
|
||||
/* Define the total number of thread relinquish operations. Each time a thread
|
||||
relinquish operation is actually performed (another thread is setup for running)
|
||||
this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_relinquish_count;
|
||||
|
||||
|
||||
/* Define the total number of thread timeouts. Each time a thread has a
|
||||
timeout this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_timeout_count;
|
||||
|
||||
|
||||
/* Define the total number of thread wait aborts. Each time a thread's suspension
|
||||
is lifted by the tx_thread_wait_abort call this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_wait_abort_count;
|
||||
|
||||
|
||||
/* Define the total number of idle system thread returns. Each time a thread returns to
|
||||
an idle system (no other thread is ready to run) this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_idle_return_count;
|
||||
|
||||
|
||||
/* Define the total number of non-idle system thread returns. Each time a thread returns to
|
||||
a non-idle system (another thread is ready to run) this variable is incremented. */
|
||||
|
||||
ULONG _tx_thread_performance_non_idle_return_count;
|
||||
|
||||
|
||||
/* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
|
||||
is a circular list, where the index points to the oldest entry. */
|
||||
|
||||
ULONG _tx_thread_performance__execute_log_index;
|
||||
TX_THREAD * _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
|
||||
#endif
|
||||
|
||||
|
||||
/* Define special string. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
const CHAR _tx_thread_special_string[] =
|
||||
"G-ML-EL-ML-BL-DL-BL-GB-GL-M-D-DL-GZ-KH-EL-CM-NH-HA-GF-DD-JC-YZ-CT-AT-DW-USA-CA-SD-SDSU";
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_initialize PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the various control data structures for */
|
||||
/* the thread control component. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level High level initialization */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_initialize(VOID)
|
||||
{
|
||||
|
||||
/* Note: the system stack pointer and the system state variables are
|
||||
initialized by the low and high-level initialization functions,
|
||||
respectively. */
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Set current thread pointer to NULL. */
|
||||
TX_THREAD_SET_CURRENT(TX_NULL)
|
||||
|
||||
/* Initialize the execute thread pointer to NULL. */
|
||||
_tx_thread_execute_ptr = TX_NULL;
|
||||
|
||||
/* Initialize the priority information. */
|
||||
TX_MEMSET(&_tx_thread_priority_maps[0], 0, (sizeof(_tx_thread_priority_maps)));
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
TX_MEMSET(&_tx_thread_preempted_maps[0], 0, (sizeof(_tx_thread_preempted_maps)));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Setup the highest priority variable to the max, indicating no thread is currently
|
||||
ready. */
|
||||
_tx_thread_highest_priority = ((UINT) TX_MAX_PRIORITIES);
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
||||
|
||||
/* Initialize the array of priority head pointers. */
|
||||
TX_MEMSET(&_tx_thread_priority_list[0], 0, (sizeof(_tx_thread_priority_list)));
|
||||
|
||||
/* Initialize the head pointer of the created threads list and the
|
||||
number of threads created. */
|
||||
_tx_thread_created_ptr = TX_NULL;
|
||||
_tx_thread_created_count = TX_EMPTY;
|
||||
|
||||
/* Clear the global preempt disable variable. */
|
||||
_tx_thread_preempt_disable = ((UINT) 0);
|
||||
|
||||
/* Initialize the thread mutex release function pointer. */
|
||||
_tx_thread_mutex_release = TX_NULL;
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
|
||||
/* Clear application registered stack error handler. */
|
||||
_tx_thread_application_stack_error_handler = TX_NULL;
|
||||
#endif
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Clear performance counters. */
|
||||
_tx_thread_performance_resume_count = ((ULONG) 0);
|
||||
_tx_thread_performance_suspend_count = ((ULONG) 0);
|
||||
_tx_thread_performance_solicited_preemption_count = ((ULONG) 0);
|
||||
_tx_thread_performance_interrupt_preemption_count = ((ULONG) 0);
|
||||
_tx_thread_performance_priority_inversion_count = ((ULONG) 0);
|
||||
_tx_thread_performance_time_slice_count = ((ULONG) 0);
|
||||
_tx_thread_performance_relinquish_count = ((ULONG) 0);
|
||||
_tx_thread_performance_timeout_count = ((ULONG) 0);
|
||||
_tx_thread_performance_wait_abort_count = ((ULONG) 0);
|
||||
_tx_thread_performance_idle_return_count = ((ULONG) 0);
|
||||
_tx_thread_performance_non_idle_return_count = ((ULONG) 0);
|
||||
|
||||
/* Initialize the execute thread log. */
|
||||
TX_MEMSET(&_tx_thread_performance_execute_log[0], 0, (sizeof(_tx_thread_performance_execute_log)));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Setup the build options flag. This is used to identify how the ThreadX library was constructed. */
|
||||
_tx_build_options = _tx_build_options
|
||||
| (((ULONG) (TX_MAX_PRIORITIES/32)) << 24)
|
||||
#ifdef TX_NOT_INTERRUPTABLE
|
||||
| (((ULONG) 1) << 31)
|
||||
#endif
|
||||
#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
|
||||
| (((ULONG) 1) << 30)
|
||||
#endif
|
||||
#ifdef TX_TIMER_PROCESS_IN_ISR
|
||||
| (((ULONG) 1) << 23)
|
||||
#endif
|
||||
#ifdef TX_REACTIVATE_INLINE
|
||||
| (((ULONG) 1) << 22)
|
||||
#endif
|
||||
#ifdef TX_DISABLE_STACK_FILLING
|
||||
| (((ULONG) 1) << 21)
|
||||
#endif
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
| (((ULONG) 1) << 20)
|
||||
#endif
|
||||
#ifdef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
| (((ULONG) 1) << 19)
|
||||
#endif
|
||||
#ifdef TX_DISABLE_REDUNDANT_CLEARING
|
||||
| (((ULONG) 1) << 18)
|
||||
#endif
|
||||
#ifdef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
| (((ULONG) 1) << 17)
|
||||
#endif
|
||||
#ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 16)
|
||||
#endif
|
||||
#ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 15)
|
||||
#endif
|
||||
#ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 14)
|
||||
#endif
|
||||
#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 13)
|
||||
#endif
|
||||
#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 12)
|
||||
#endif
|
||||
#ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 11)
|
||||
#endif
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 10)
|
||||
#endif
|
||||
#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
|
||||
| (((ULONG) 1) << 9)
|
||||
#endif
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
| (((ULONG) 1) << 8)
|
||||
#endif
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
| (((ULONG) 1) << 7)
|
||||
#endif
|
||||
#if TX_PORT_SPECIFIC_BUILD_OPTIONS != 0
|
||||
| TX_PORT_SPECIFIC_BUILD_OPTIONS
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
297
common/src/tx_thread_performance_info_get.c
Normal file
297
common/src/tx_thread_performance_info_get.c
Normal file
@ -0,0 +1,297 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_performance_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves performance information from the specified */
|
||||
/* thread. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control block */
|
||||
/* resumptions Destination for number of times */
|
||||
/* thread was resumed */
|
||||
/* suspensions Destination for number of times */
|
||||
/* thread was suspended */
|
||||
/* solicited_preemptions Destination for number of times */
|
||||
/* thread called another service */
|
||||
/* that resulted in preemption */
|
||||
/* interrupt_preemptions Destination for number of times */
|
||||
/* thread was preempted by another */
|
||||
/* thread made ready in Interrupt */
|
||||
/* Service Routine (ISR) */
|
||||
/* priority_inversions Destination for number of times */
|
||||
/* a priority inversion was */
|
||||
/* detected for this thread */
|
||||
/* time_slices Destination for number of times */
|
||||
/* thread was time-sliced */
|
||||
/* relinquishes Destination for number of thread */
|
||||
/* relinquishes */
|
||||
/* timeouts Destination for number of timeouts*/
|
||||
/* for thread */
|
||||
/* wait_aborts Destination for number of wait */
|
||||
/* aborts for thread */
|
||||
/* last_preempted_by Destination for pointer of the */
|
||||
/* thread that last preempted this */
|
||||
/* thread */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_performance_info_get(TX_THREAD *thread_ptr, ULONG *resumptions, ULONG *suspensions,
|
||||
ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
|
||||
ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts, TX_THREAD **last_preempted_by)
|
||||
{
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine if this is a legal request. */
|
||||
if (thread_ptr == TX_NULL)
|
||||
{
|
||||
|
||||
/* Thread pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
|
||||
/* Determine if the thread ID is invalid. */
|
||||
else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
|
||||
{
|
||||
|
||||
/* Thread pointer is illegal, return error. */
|
||||
status = TX_PTR_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_INFO_GET, thread_ptr, thread_ptr -> tx_thread_state, 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_PERFORMANCE_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve number of resumptions for this thread. */
|
||||
if (resumptions != TX_NULL)
|
||||
{
|
||||
|
||||
*resumptions = thread_ptr -> tx_thread_performance_resume_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of suspensions for this thread. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = thread_ptr -> tx_thread_performance_suspend_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of solicited preemptions for this thread. */
|
||||
if (solicited_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
*solicited_preemptions = thread_ptr -> tx_thread_performance_solicited_preemption_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of interrupt preemptions for this thread. */
|
||||
if (interrupt_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
*interrupt_preemptions = thread_ptr -> tx_thread_performance_interrupt_preemption_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of priority inversions for this thread. */
|
||||
if (priority_inversions != TX_NULL)
|
||||
{
|
||||
|
||||
*priority_inversions = thread_ptr -> tx_thread_performance_priority_inversion_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of time-slices for this thread. */
|
||||
if (time_slices != TX_NULL)
|
||||
{
|
||||
|
||||
*time_slices = thread_ptr -> tx_thread_performance_time_slice_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of relinquishes for this thread. */
|
||||
if (relinquishes != TX_NULL)
|
||||
{
|
||||
|
||||
*relinquishes = thread_ptr -> tx_thread_performance_relinquish_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of timeouts for this thread. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = thread_ptr -> tx_thread_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Retrieve number of wait aborts for this thread. */
|
||||
if (wait_aborts != TX_NULL)
|
||||
{
|
||||
|
||||
*wait_aborts = thread_ptr -> tx_thread_performance_wait_abort_count;
|
||||
}
|
||||
|
||||
/* Retrieve the pointer of the last thread that preempted this thread. */
|
||||
if (last_preempted_by != TX_NULL)
|
||||
{
|
||||
|
||||
*last_preempted_by = thread_ptr -> tx_thread_performance_last_preempting_thread;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
status = TX_SUCCESS;
|
||||
}
|
||||
#else
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (resumptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (solicited_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (interrupt_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (priority_inversions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (time_slices != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (relinquishes != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (wait_aborts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (last_preempted_by != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
287
common/src/tx_thread_performance_system_info_get.c
Normal file
287
common/src/tx_thread_performance_system_info_get.c
Normal file
@ -0,0 +1,287 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
#include "tx_trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_performance_system_info_get PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function retrieves thread system performance information. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* resumptions Destination for total number of */
|
||||
/* thread resumptions */
|
||||
/* suspensions Destination for total number of */
|
||||
/* thread suspensions */
|
||||
/* solicited_preemptions Destination for total number of */
|
||||
/* thread preemption from thread */
|
||||
/* API calls */
|
||||
/* interrupt_preemptions Destination for total number of */
|
||||
/* thread preemptions as a result */
|
||||
/* of threads made ready inside of */
|
||||
/* Interrupt Service Routines */
|
||||
/* priority_inversions Destination for total number of */
|
||||
/* priority inversions */
|
||||
/* time_slices Destination for total number of */
|
||||
/* time-slices */
|
||||
/* relinquishes Destination for total number of */
|
||||
/* relinquishes */
|
||||
/* timeouts Destination for total number of */
|
||||
/* timeouts */
|
||||
/* wait_aborts Destination for total number of */
|
||||
/* wait aborts */
|
||||
/* non_idle_returns Destination for total number of */
|
||||
/* times threads return when */
|
||||
/* another thread is ready */
|
||||
/* idle_returns Destination for total number of */
|
||||
/* times threads return when no */
|
||||
/* other thread is ready */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_performance_system_info_get(ULONG *resumptions, ULONG *suspensions,
|
||||
ULONG *solicited_preemptions, ULONG *interrupt_preemptions, ULONG *priority_inversions,
|
||||
ULONG *time_slices, ULONG *relinquishes, ULONG *timeouts, ULONG *wait_aborts,
|
||||
ULONG *non_idle_returns, ULONG *idle_returns)
|
||||
{
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PERFORMANCE_SYSTEM_INFO_GET, 0, 0, 0, 0, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_PERFORMANCE_SYSTEM_INFO_GET_INSERT
|
||||
|
||||
/* Retrieve all the pertinent information and return it in the supplied
|
||||
destinations. */
|
||||
|
||||
/* Retrieve total number of thread resumptions. */
|
||||
if (resumptions != TX_NULL)
|
||||
{
|
||||
|
||||
*resumptions = _tx_thread_performance_resume_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread suspensions. */
|
||||
if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
*suspensions = _tx_thread_performance_suspend_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of solicited thread preemptions. */
|
||||
if (solicited_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
*solicited_preemptions = _tx_thread_performance_solicited_preemption_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of interrupt thread preemptions. */
|
||||
if (interrupt_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
*interrupt_preemptions = _tx_thread_performance_interrupt_preemption_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread priority inversions. */
|
||||
if (priority_inversions != TX_NULL)
|
||||
{
|
||||
|
||||
*priority_inversions = _tx_thread_performance_priority_inversion_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread time-slices. */
|
||||
if (time_slices != TX_NULL)
|
||||
{
|
||||
|
||||
*time_slices = _tx_thread_performance_time_slice_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread relinquishes. */
|
||||
if (relinquishes != TX_NULL)
|
||||
{
|
||||
|
||||
*relinquishes = _tx_thread_performance_relinquish_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread timeouts. */
|
||||
if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
*timeouts = _tx_thread_performance_timeout_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread wait aborts. */
|
||||
if (wait_aborts != TX_NULL)
|
||||
{
|
||||
|
||||
*wait_aborts = _tx_thread_performance_wait_abort_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread non-idle system returns. */
|
||||
if (non_idle_returns != TX_NULL)
|
||||
{
|
||||
|
||||
*non_idle_returns = _tx_thread_performance_non_idle_return_count;
|
||||
}
|
||||
|
||||
/* Retrieve total number of thread idle system returns. */
|
||||
if (idle_returns != TX_NULL)
|
||||
{
|
||||
|
||||
*idle_returns = _tx_thread_performance_idle_return_count;
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(TX_SUCCESS);
|
||||
|
||||
#else
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Access input arguments just for the sake of lint, MISRA, etc. */
|
||||
if (resumptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (suspensions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (solicited_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (interrupt_preemptions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (priority_inversions != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (time_slices != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (relinquishes != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (timeouts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (wait_aborts != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (non_idle_returns != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else if (idle_returns != TX_NULL)
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Not enabled, return error. */
|
||||
status = TX_FEATURE_NOT_ENABLED;
|
||||
}
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
#endif
|
||||
}
|
||||
|
280
common/src/tx_thread_preemption_change.c
Normal file
280
common/src/tx_thread_preemption_change.c
Normal file
@ -0,0 +1,280 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_trace.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_preemption_change PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes preemption-threshold change requests. The */
|
||||
/* previous preemption is returned to the caller. If the new request */
|
||||
/* allows a higher priority thread to execute, preemption takes place */
|
||||
/* inside of this function. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread */
|
||||
/* new_threshold New preemption threshold */
|
||||
/* old_threshold Old preemption threshold */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Service return status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_system_preempt_check Check for preemption */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, UINT *old_threshold)
|
||||
{
|
||||
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
ULONG priority_bit;
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
UINT map_index;
|
||||
#endif
|
||||
#endif
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Default status to success. */
|
||||
status = TX_SUCCESS;
|
||||
|
||||
#ifdef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Only allow 0 (disable all preemption) and returning preemption-threshold to the
|
||||
current thread priority if preemption-threshold is disabled. All other threshold
|
||||
values are converted to 0. */
|
||||
if (thread_ptr -> tx_thread_user_priority != new_threshold)
|
||||
{
|
||||
|
||||
/* Is the new threshold zero? */
|
||||
if (new_threshold != ((UINT) 0))
|
||||
{
|
||||
|
||||
/* Convert the new threshold to disable all preemption, since preemption-threshold is
|
||||
not supported. */
|
||||
new_threshold = ((UINT) 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Lockout interrupts while the thread is being resumed. */
|
||||
TX_DISABLE
|
||||
|
||||
/* If trace is enabled, insert this event into the trace buffer. */
|
||||
TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_PREEMPTION_CHANGE, thread_ptr, new_threshold, thread_ptr -> tx_thread_preempt_threshold, thread_ptr -> tx_thread_state, TX_TRACE_THREAD_EVENTS)
|
||||
|
||||
/* Log this kernel call. */
|
||||
TX_EL_THREAD_PREEMPTION_CHANGE_INSERT
|
||||
|
||||
/* Determine if the new threshold is greater than the current user priority. */
|
||||
if (new_threshold > thread_ptr -> tx_thread_user_priority)
|
||||
{
|
||||
|
||||
/* Return error. */
|
||||
status = TX_THRESH_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Determine if the new threshold is the same as the priority. */
|
||||
if (thread_ptr -> tx_thread_user_priority == new_threshold)
|
||||
{
|
||||
|
||||
/* Determine if this thread is at the head of the list. */
|
||||
if (_tx_thread_priority_list[thread_ptr -> tx_thread_priority] == thread_ptr)
|
||||
{
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
|
||||
/* Calculate the index into the bit map array. */
|
||||
map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32);
|
||||
#endif
|
||||
|
||||
/* Yes, this thread is at the front of the list. Make sure
|
||||
the preempted bit is cleared for this thread. */
|
||||
TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] & (~(priority_bit));
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
|
||||
/* Determine if there are any other bits set in this preempt map. */
|
||||
if (_tx_thread_preempted_maps[MAP_INDEX] == ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* No, clear the active bit to signify this preempt map has nothing set. */
|
||||
TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_map_active = _tx_thread_preempted_map_active & (~(priority_bit));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the user's preemption-threshold. */
|
||||
*old_threshold = thread_ptr -> tx_thread_user_preempt_threshold;
|
||||
|
||||
/* Setup the new threshold. */
|
||||
thread_ptr -> tx_thread_user_preempt_threshold = new_threshold;
|
||||
|
||||
/* Determine if the new threshold represents a higher priority than the priority inheritance threshold. */
|
||||
if (new_threshold < thread_ptr -> tx_thread_inherit_priority)
|
||||
{
|
||||
|
||||
/* Update the actual preemption-threshold with the new threshold. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = new_threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Update the actual preemption-threshold with the priority inheritance. */
|
||||
thread_ptr -> tx_thread_preempt_threshold = thread_ptr -> tx_thread_inherit_priority;
|
||||
}
|
||||
|
||||
/* Is the thread priority less than the current highest priority? If not, no preemption is required. */
|
||||
if (_tx_thread_highest_priority < thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
/* Is the new thread preemption-threshold less than the current highest priority? If not, no preemption is required. */
|
||||
if (_tx_thread_highest_priority < new_threshold)
|
||||
{
|
||||
|
||||
/* If the current execute pointer is the same at this thread, preemption needs to take place. */
|
||||
if (_tx_thread_execute_ptr == thread_ptr)
|
||||
{
|
||||
|
||||
/* Preemption needs to take place. */
|
||||
|
||||
#ifndef TX_DISABLE_PREEMPTION_THRESHOLD
|
||||
|
||||
/* Determine if this thread has preemption threshold set. */
|
||||
if (thread_ptr -> tx_thread_preempt_threshold != thread_ptr -> tx_thread_priority)
|
||||
{
|
||||
|
||||
#if TX_MAX_PRIORITIES > 32
|
||||
|
||||
/* Calculate the index into the bit map array. */
|
||||
map_index = (thread_ptr -> tx_thread_priority)/((UINT) 32);
|
||||
|
||||
/* Set the active bit to remember that the preempt map has something set. */
|
||||
TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_map_active = _tx_thread_preempted_map_active | priority_bit;
|
||||
#endif
|
||||
|
||||
/* Remember that this thread was preempted by a thread above the thread's threshold. */
|
||||
TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
|
||||
_tx_thread_preempted_maps[MAP_INDEX] = _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
|
||||
/* Determine if the caller is an interrupt or from a thread. */
|
||||
if (TX_THREAD_GET_SYSTEM_STATE() == ((ULONG) 0))
|
||||
{
|
||||
|
||||
/* Caller is a thread, so this is a solicited preemption. */
|
||||
_tx_thread_performance_solicited_preemption_count++;
|
||||
|
||||
/* Increment the thread's solicited preemption counter. */
|
||||
thread_ptr -> tx_thread_performance_solicited_preemption_count++;
|
||||
}
|
||||
|
||||
/* Remember the thread that preempted this thread. */
|
||||
thread_ptr -> tx_thread_performance_last_preempting_thread = _tx_thread_priority_list[_tx_thread_highest_priority];
|
||||
|
||||
/* Is the execute pointer different? */
|
||||
if (_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] != _tx_thread_execute_ptr)
|
||||
{
|
||||
|
||||
/* Move to next entry. */
|
||||
_tx_thread_performance__execute_log_index++;
|
||||
|
||||
/* Check for wrap condition. */
|
||||
if (_tx_thread_performance__execute_log_index >= TX_THREAD_EXECUTE_LOG_SIZE)
|
||||
{
|
||||
|
||||
/* Set the index to the beginning. */
|
||||
_tx_thread_performance__execute_log_index = ((UINT) 0);
|
||||
}
|
||||
|
||||
/* Log the new execute pointer. */
|
||||
_tx_thread_performance_execute_log[_tx_thread_performance__execute_log_index] = _tx_thread_execute_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup the highest priority thread to execute. */
|
||||
_tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Check for preemption. */
|
||||
_tx_thread_system_preempt_check();
|
||||
|
||||
/* Disable interrupts. */
|
||||
TX_DISABLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore interrupts. */
|
||||
TX_RESTORE
|
||||
|
||||
/* Return completion status. */
|
||||
return(status);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user