libcoap 4.3.4-develop-9f1418e
coap_locking

SYNOPSIS

#include <coap3/coap.h>

void coap_lock_init(coap_context_t *context);

void coap_lock_lock(coap_context_t *context, coap_code_t failed_statement);

void coap_lock_unlock(coap_context_t *context);

void coap_lock_being_freed(coap_context_t *context, coap_code_t failed_statement);

void coap_lock_check_locked(coap_context_t *context);

void coap_lock_callback(coap_context_t *context, coap_func_t callback_function);

void coap_lock_callback_ret(void *return_value, coap_context_t *context, coap_func_t callback_function, coap_code_t failed_statement);

void coap_lock_invert(coap_context_t *context, coap_func_t locking_function, coap_code_t failed_statement);

For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls, -lcoap-3-wolfssl or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default (D)TLS library support.

DESCRIPTION

This man page focuses on the locking support provided for making libcoap thread safe. Usage is internal to libcoap.

The functions are actually macros which create different code depending on what levels of locking has been configured. Locking uses coap_mutex_() functions.

So, failed_statement is the C code to execute if the locking fails for any reason.

Likewise, callback_function is the callback handler function with all of its parameters.

Several definitions can be defined with configure or cmake. These are

COAP_THREAD_SAFE If set, simply does locking at the appropriate places. If not set, then no locking takes place, the code is faster (no locking code), but not multi-thread access safe.

COAP_THREAD_RECURSIVE_CHECK If set, and COAP_THREAD_SAFE is set, checks that if a lock is locked, it reports that the same lock is being (re-)locked.

Currently, locking is only done at the context level for the public API functions where appropriate. Per session was also considered, but things became complicated with one thread locking context / session and another thread trying to lock session / context in a different order.

In principal, libcoap code internally should only unlock context when waiting on a select() or equivalent, and then lock up again on function return.

context needs to remain locked whenever a callback handler is called, and it is possible / likely that the handler will call a public API which potentially could try to re-lock the same lock. By using coap_lock_callback() (or coap_lock_callback_ret()), the locking logic can detect that this lock request is from a callback handler and so continue without any deadlocks.

If COAP_THREAD_SAFE is set, then all the necessary public APIs are defined in src/coap_threadsafe.c. These public APIs then call the same function after locking, but with _locked appended to the function name. In otherwords, coap_X() calls coap_lock_lock(), then calls coap_X_locked(), and finally calls coap_lock_unlock() before returning.

The internal renaming of coap_X() functions to coap_X_locked() is done by macros in include/coap3/coap_threadsafe_internal.h, which also provides the coap_X_locked() function definitions.

FUNCTIONS

Function: coap_lock_init()

The coap_lock_init() function is used to initialize the lock structure in the context structure.

Function: coap_lock_lock()

The coap_lock_lock() function is used to lock context from multiple thread access. If the locking fails for any reason, then failed_statement will get executed.

Function: coap_lock_unlock()

The coap_lock_unlock() function is used to unlock context so that another thread can access context and the underlying structures.

Function: coap_lock_being_freed()

The coap_lock_being_freed() function is used to lock context when context and all the underlying structures are going to be released (called from coap_free_context(3)). Any subsequent call to coap_lock_lock() by another thread will fail. If this locking fails for any reason, then failed_statement will get executed.

Function: coap_lock_check_lock()

The coap_lock_check_lock() function is used to check the internal version (potentially has _locked appended in the name) of a public AP is getting called with context locked.

Function: coap_lock_callback()

The coap_lock_callback() function is used whenever a callback handler is getting called, instead of calling the function directly. The lock information in context is updated so that if a public API is called from within the handler, recursive locking is enabled for that particular thread. On return from the callback, the lock in context is suitably restored. callback_function is the callback handler to be called, along with all of the appropriate parameters.

Function: coap_lock_callback_ret()

The coap_lock_callback_ret() function is similar to coap_lock_callback(), but in addition, it updates the return value from the callback handler function in return_value.

Function: coap_lock_invert()

The coap_lock_invert() function is used where there are other locking mechanisms external to libcoap and the locking order needs to be external lock, then libcoap code locked. context already needs to be locked before calling coap_lock_invert(). If coap_lock_invert() is called, then context will get unlocked, locking_function with all of its parameters called, and then context re-locked. If for any reason locking fails, then failed_statement will get executed.

SEE ALSO

coap_context(3)

FURTHER INFORMATION

See

"RFC7252: The Constrained Application Protocol (CoAP)"

for further information.

BUGS

Please raise an issue on GitHub at https://github.com/obgm/libcoap/issues to report any bugs.

Please raise a Pull Request at https://github.com/obgm/libcoap/pulls for any fixes.

AUTHORS

The libcoap project <libcoap-developers@lists.sourceforge.net>

coap_lock_callback(3)