Chapter 4 - Module APIs
There are several additional API functions available to a module, as follows:
Return values
Additional error codes are returned for some ThreadX APIs. These additional error codes are defined as follows:
-
TXM_MODULE_INVALID_PROPERTIES (0xF3): Indicates the module does not have the correct properties to make an API call. For example, calling trace APIs in user mode.
-
TXM_MODULE_INVALID_MEMORY (0xF4): Indicates the memory supplied by the module is invalid or is in an invalid location. For example, in memory protected modules, object control blocks are not allowed to be located in memory the module can access.
-
TXM_MODULE_INVALID_CALLBACK (0xF5): Callback specified in the API is outside the range of the module’s code and is therefore invalid.
-
TXM_MODULE_MATH_OVERFLOW (0xF8): A size supplied by the module is too large for the module manager to work with. The manager adds its own bookkeeping to the sizes it is given, and refuses a size for which that addition would not be representable rather than proceeding on a value that has wrapped.
txm_module_application_request
Application-specific request to resident code.
Prototype
UINT txm_module_application_request(
ULONG request,
ULONG param_1,
ULONG param_2,
ULONG param_3);
Description
This service makes the specified request to the resident portion of the application. It is assumed that the request structure is prepared prior to the call. The actual processing of the request takes place in the resident code in the function _txm_module_manager_application_request. By default, this function is left empty and is designed for the resident application developer to modify.
Input parameters
-
request Request ID (application defined)
-
param_1 First parameter
-
param_2 Second parameter
-
param_3 Third parameter
Return values
-
TX_SUCCESS (0x00) Successful request.
-
TX_NOT_AVAILABLE (0x1D) Request not supported by resident code.
Example
/* Call application resident code with ID=77 and the
parameters set to 1, 2, 3. */
status = txm_module_application_request(77, 1, 2, 3);
/* If status is TX_SUCCESS the request was successful. */
txm_module_object_allocate
Allocate memory in the object pool (created by the resident application) for a module object control block.
Description
This service allocates memory for a module object from memory outside of the module, which helps prevent corruption of the object control block by the module’s code. In memory protected systems, all object control blocks must be allocated with this API before they can be created.
The module manager allocates more than object_size bytes: it keeps a header of its own in front of the memory the module receives, recording the owning module, the size and the links that let the allocation be reclaimed when the module is unloaded. object_size is therefore bounded above by what the object pool holds, less that header, and a size too large to add the header to at all is refused with TXM_MODULE_MATH_OVERFLOW. Pass sizeof the control block being allocated, as in the example below.
Input parameters
-
object_ptr Destination of object pointer on successful allocation.
-
object_size Size in bytes of the object to be allocated.
Return values
-
TX_SUCCESS (0x00) Successful object allocate.
-
TX_SIZE_ERROR (0x05) object_size, together with the manager’s own object header, is larger than the whole object pool.
-
TX_NO_MEMORY (0x10) Not enough memory.
-
TX_NOT_AVAILABLE (0x1D) Module manager has not created an object pool to allocate from
-
TXM_MODULE_INVALID_MEMORY (0xF4) object_ptr is NULL, so there is nowhere to return the allocation.
-
TXM_MODULE_MATH_OVERFLOW (0xF8) object_size is so large that adding the manager’s own object header to it would not be representable. Nothing is allocated and the object pool is left untouched.
Example
TX_QUEUE *queue_pointer;
/* Allocate a control block for a module message queue. */
status = txm_module_object_allocate(&queue_pointer, sizeof(TX_QUEUE));
/* If status is TX_SUCCESS the queue_pointer points to
memory allocated outside of the module and can be supplied
to tx_queue_create to create a queue for the module. */
txm_module_object_deallocate
Deallocate previously allocated object memory
| This service is deprecated. Do not use it in new code, and remove any existing calls from your modules. |
Reason for deprecation
When a module calls a standard kernel delete service such as tx_timer_delete, tx_semaphore_delete, tx_queue_delete, or any other tx*delete service, the Module Manager dispatch layer automatically releases the associated object pool memory after the kernel cleanup completes. No separate deallocation call is required.
Deallocation is not deletion. Calling txm_module_object_deallocate on a live kernel object — one whose tx*delete service has not yet been called — asks the Module Manager to release memory the kernel is still using as a control block: the object remains on the created list for its type, a thread remains schedulable, and an active timer remains on the timer list, none of which look at whether the memory has been given back. The Module Manager therefore refuses such a request and returns TX_DELETE_ERROR, leaving the object, the allocation and the memory exactly as they were. Delete the object first.
Memory that holds no live object is still released, so a module can still give back storage it allocated for an object it never created, or for one it has since deleted.
What to do instead
Remove any call to txm_module_object_deallocate from your module. Calling the appropriate tx*delete service is sufficient; pool memory deallocation is handled automatically by the Module Manager dispatch layer.
TX_TIMER my_timer;
/* Allocate and create the timer. */
txm_module_object_allocate(&my_timer, sizeof(TX_TIMER));
tx_timer_create(&my_timer, "my timer", my_callback, 0, 10, 10, TX_AUTO_ACTIVATE);
/* When done: delete the timer. The dispatch layer releases pool memory
automatically. Do NOT call txm_module_object_deallocate. */
tx_timer_delete(&my_timer);
Return values
-
TX_SUCCESS (0x00) Successful object deallocation.
-
TX_DELETE_ERROR (0x11) The memory holds a live kernel object. Nothing was released. Call the object’s tx*delete service, which releases the memory itself.
-
TX_PTR_ERROR (0x03) The address is not one the Module Manager handed this module, or the module has no allocations.
-
TX_NOT_AVAILABLE (0x1D) No Module Manager object pool has been created.
-
TXM_MODULE_INVALID_MEMORY (0xF4) The address does not lie inside the object pool with room for the manager’s private header in front of it and for the allocation the header describes.
txm_module_object_pointer_get
Find system object and retrieve object pointer
| This service is deprecated. Do not use it in new code. Use txm_module_object_pointer_get_extended instead, passing the actual length of the name buffer. |
This function passes UINT_MAX as the name-buffer length to the underlying search. If the name pointer addresses a buffer shorter than the object name being compared, the comparison loop reads past the end of the buffer, which is undefined behavior.
Because no length is passed, the Module Manager cannot establish how much of the buffer it is allowed to read, and a module loaded with TXM_MODULE_MEMORY_PROTECTION is therefore refused this service with TXM_MODULE_INVALID_MEMORY. Such a module must use txm_module_object_pointer_get_extended. Modules loaded without memory protection are unaffected.
Description
Deprecated — see above. This service retrieves the object pointer of a particular type with a particular name. If the object is not found, an error is returned. Otherwise, if the object is found, the address of that object is placed in "object_ptr."
The pointer this service returns grants use of the object, not authority to destroy it. See txm_module_object_pointer_get_extended.
Input parameters
-
object_type Type of ThreadX object requested. Valid types are as follows:
-
TXM_BLOCK_POOL_OBJECT
-
TXM_BYTE_POOL_OBJECT
-
TXM_EVENT_FLAGS_OBJECT
-
TXM_MUTEX_OBJECT
-
TXM_QUEUE_OBJECT
-
TXM_SEMAPHORE_OBJECT
-
TXM_THREAD_OBJECT
-
TXM_TIMER_OBJECT
-
TXM_IP_OBJECT
-
TXM_PACKET_POOL_OBJECT
-
TXM_UDP_SOCKET_OBJECT
-
TXM_TCP_SOCKET_OBJECT
-
-
name Application-specific object name as defined when the object was created.
-
object_ptr Destination for object pointer.
Return values
-
TX_SUCCESS (0x00) Successful object get.
-
TX_OPTION_ERROR (0x08) Invalid object type.
-
TX_PTR_ERROR (0x03) Invalid destination.
-
TX_SIZE_ERROR (0x05) Invalid size.
-
TX_NO_INSTANCE (0x0D) Object not found.
-
TXM_MODULE_INVALID (0xF2) A memory-protected module asked for a block pool or a byte pool.
-
TXM_MODULE_INVALID_MEMORY (0xF4) The requesting module is memory-protected, and this service cannot bound the read.
Example
TX_QUEUE *queue_pointer;
/* Find the pointer for "fft_queue" in the resident part
of the application. */
status = txm_module_object_pointer_get(TXM_QUEUE_OBJECT,
"fft_queue", &queue_pointer);
/* If status is TX_SUCCESS the found queue pointer is in
"queue_pointer". This queue pointer can then be used to
send messages to the "fft_queue." */
txm_module_object_pointer_get_extended
Find system object and retrieve object pointer
Prototype
UINT txm_module_object_pointer_get_extended(UINT object_type,
CHAR *name,
UINT name_length,
VOID **object_ptr);
Description
This service retrieves the object pointer of a particular type with a particular name. If the object is not found, an error is returned. Otherwise, if the object is found, the address of that object is placed in "object_ptr." This pointer can then be used to make system service calls, to interact with the resident code, and/or other loaded modules in the system.
The pointer grants use of the object, not authority to destroy it. A memory-protected module may only delete a kernel object it allocated for itself from the Module Manager’s object pool; passing a pointer obtained here to tx_queue_delete, tx_semaphore_delete or any other tx*delete service returns TXM_MODULE_INVALID_MEMORY and leaves the object created and its waiters undisturbed. Objects a module does not own are shared with it to be used, and the owner remains responsible for deleting them.
A memory-protected module cannot look up a block pool or a byte pool at all: TXM_BLOCK_POOL_OBJECT and TXM_BYTE_POOL_OBJECT return TXM_MODULE_INVALID for such a module, which may use only the pools it created itself.
Input parameters
-
object_type Type of ThreadX object requested. Valid types are as follows:
-
TXM_BLOCK_POOL_OBJECT
-
TXM_BYTE_POOL_OBJECT
-
TXM_EVENT_FLAGS_OBJECT
-
TXM_MUTEX_OBJECT
-
TXM_QUEUE_OBJECT
-
TXM_SEMAPHORE_OBJECT
-
TXM_THREAD_OBJECT
-
TXM_TIMER_OBJECT
-
TXM_IP_OBJECT
-
TXM_PACKET_POOL_OBJECT
-
TXM_UDP_SOCKET_OBJECT
-
TXM_TCP_SOCKET_OBJECT
-
-
name Application-specific object name as defined when the object was created.
-
name_length Number of characters in name, not counting the terminating null character. Passing
strlen(name)is correct; passingsizeofa string literal is one too many. -
object_ptr Destination for object pointer.
The search compares the name a character at a time and stops at the terminating null, so it reads name_length + 1 bytes at most: the characters, and the terminator that follows them. For a module loaded with TXM_MODULE_MEMORY_PROTECTION the whole of that range, from name[0] through name[name_length], must be inside memory the module may read — its own data, its own code, or shared memory registered to it. A request whose range is not entirely readable is refused with TXM_MODULE_INVALID_MEMORY before any comparison is made, so a name buffer at the very end of a region must have room for the terminator as well as the characters.
A name_length of UINT_MAX is always refused, because the range it describes cannot be expressed.
Return values
-
TX_SUCCESS (0x00) Successful object get.
-
TX_OPTION_ERROR (0x08) Invalid object type.
-
TX_PTR_ERROR (0x03) Invalid destination.
-
TX_SIZE_ERROR (0x05) Invalid size.
-
TX_NO_INSTANCE (0x0D) Object not found.
-
TXM_MODULE_INVALID (0xF2) A memory-protected module asked for a block pool or a byte pool.
-
TXM_MODULE_INVALID_MEMORY (0xF4) The name range, or the destination, is not memory the requesting module may use.
Example
TX_QUEUE *queue_pointer;
/* Find the pointer for "fft_queue" in the resident part
of the application. The name is nine characters, and the
tenth byte of the buffer is its terminator. */
status = txm_module_object_pointer_get_extended(TXM_QUEUE_OBJECT,
"fft_queue", 9, &queue_pointer);
/* If status is TX_SUCCESS the found queue pointer is in
"queue_pointer". This queue pointer can then be used to
send messages to the "fft_queue." */