sys: onoff: generalize and shorten API
The original API was misnamed, as the intent was to provide a manager that decoupled state management from the service that needed to be turned on or off. Update all the names, shortening them where appropriate removing unncessary internal components like _service. Also remove some API that misled developers into believing that onoff managers are normally expected to be exposed directly to consumers. While this is a use case, in most situations there are service or client-specific actions that need to be coupled to transition events. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
fadd98aad2
commit
8bd676ed38
4 changed files with 344 additions and 328 deletions
|
@ -10,21 +10,24 @@ complexity of properly managing multiple consumers of a device in a
|
||||||
multithreaded system, especially when transitions may be asynchronous,
|
multithreaded system, especially when transitions may be asynchronous,
|
||||||
suggests that a shared implementation is desirable.
|
suggests that a shared implementation is desirable.
|
||||||
|
|
||||||
|
Zephyr provides managers for several coordination policies. These
|
||||||
|
managers are embedded into services that use them for specific
|
||||||
|
functions.
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
:depth: 2
|
:depth: 2
|
||||||
|
|
||||||
|
|
||||||
.. _resource_mgmt_onoff:
|
.. _resource_mgmt_onoff:
|
||||||
|
|
||||||
On-Off Services
|
On-Off Manager
|
||||||
***************
|
**************
|
||||||
|
|
||||||
An on-off service supports an arbitrary number of clients of a service
|
An on-off manager supports an arbitrary number of clients of a service
|
||||||
which has a binary state. Example applications are power rails, clocks,
|
which has a binary state. Example applications are power rails, clocks,
|
||||||
and binary device power management.
|
and binary device power management.
|
||||||
|
|
||||||
The service has the following properties:
|
The manager has the following properties:
|
||||||
|
|
||||||
* The stable states are off, on, and error. The service always begins
|
* The stable states are off, on, and error. The service always begins
|
||||||
in the off state. The service may also be in a transition to a given
|
in the off state. The service may also be in a transition to a given
|
||||||
|
@ -39,8 +42,8 @@ The service has the following properties:
|
||||||
* Each service configuration provides functions that implement the
|
* Each service configuration provides functions that implement the
|
||||||
transition from off to on, from on to off, and optionally from an
|
transition from off to on, from on to off, and optionally from an
|
||||||
error state to off. Transitions that may put a calling thread to
|
error state to off. Transitions that may put a calling thread to
|
||||||
sleep must be flagged in the configuration to support safe invocation
|
sleep must be flagged in the configuration to support detecting unsafe
|
||||||
from non-thread context.
|
invocation from non-thread context.
|
||||||
* All operations are asynchronous, and are initiated by a function call
|
* All operations are asynchronous, and are initiated by a function call
|
||||||
that references a specific service and is given client notification
|
that references a specific service and is given client notification
|
||||||
data. The function call will succeed or fail. On success, the
|
data. The function call will succeed or fail. On success, the
|
||||||
|
@ -58,15 +61,15 @@ Requests are reference counted, but not tracked. That means clients are
|
||||||
responsible for recording whether their requests were accepted, and for
|
responsible for recording whether their requests were accepted, and for
|
||||||
initiating a release only if they have previously successfully completed
|
initiating a release only if they have previously successfully completed
|
||||||
a request. Improper use of the API can cause an active client to be
|
a request. Improper use of the API can cause an active client to be
|
||||||
shut out, and the service does not maintain a record of specific clients
|
shut out, and the manager does not maintain a record of specific clients
|
||||||
that have been granted a request.
|
that have been granted a request.
|
||||||
|
|
||||||
Failures in executing a transition are recorded and inhibit further
|
Failures in executing a transition are recorded and inhibit further
|
||||||
requests or releases until the service is reset. Pending requests are
|
requests or releases until the manager is reset. Pending requests are
|
||||||
notified (and cancelled) when errors are discovered.
|
notified (and cancelled) when errors are discovered.
|
||||||
|
|
||||||
Transition operation completion notifications are provided through any
|
Transition operation completion notifications are provided through the
|
||||||
of the following mechanisms:
|
standard :ref:`async_notification`, supporting these methods:
|
||||||
|
|
||||||
* Signal: A pointer to a :c:type:`struct k_poll_signal` is provided, and
|
* Signal: A pointer to a :c:type:`struct k_poll_signal` is provided, and
|
||||||
the signal is raised when the transition completes. The operation
|
the signal is raised when the transition completes. The operation
|
||||||
|
@ -81,5 +84,5 @@ Synchronous transition may be implemented by a caller based on its
|
||||||
context, for example by using :cpp:func:`k_poll()` to wait until the
|
context, for example by using :cpp:func:`k_poll()` to wait until the
|
||||||
completion is signalled.
|
completion is signalled.
|
||||||
|
|
||||||
.. doxygengroup:: resource_mgmt_apis
|
.. doxygengroup:: resource_mgmt_onoff_apis
|
||||||
:project: Zephyr
|
:project: Zephyr
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -16,7 +17,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup resource_mgmt_apis Resource Management APIs
|
* @defgroup resource_mgmt_onoff_apis On-Off Service APIs
|
||||||
* @ingroup kernel_apis
|
* @ingroup kernel_apis
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
@ -24,58 +25,64 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* @brief Flag fields used to specify on-off service behavior.
|
* @brief Flag fields used to specify on-off service behavior.
|
||||||
*/
|
*/
|
||||||
enum onoff_service_flags {
|
enum onoff_manager_flags {
|
||||||
/**
|
/**
|
||||||
* @brief Flag used in struct onoff_service_transitions.
|
* @brief Flag used in struct onoff_manager_transitions.
|
||||||
*
|
*
|
||||||
* When provided this indicates the start transition function
|
* When provided this indicates the start transition function
|
||||||
* may cause the calling thread to wait. This blocks attempts
|
* may cause the calling thread to wait. This blocks attempts
|
||||||
* to initiate a transition from a non-thread context.
|
* to initiate a transition from a non-thread context.
|
||||||
*/
|
*/
|
||||||
ONOFF_SERVICE_START_SLEEPS = BIT(0),
|
ONOFF_START_SLEEPS = BIT(0),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Flag used in struct onoff_service_transitions.
|
* @brief Flag used in struct onoff_manager_transitions.
|
||||||
*
|
*
|
||||||
* As with @ref ONOFF_SERVICE_START_SLEEPS but describing the
|
* As with @ref ONOFF_START_SLEEPS but describing the stop
|
||||||
* stop transition function.
|
* transition function.
|
||||||
*/
|
*/
|
||||||
ONOFF_SERVICE_STOP_SLEEPS = BIT(1),
|
ONOFF_STOP_SLEEPS = BIT(1),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Flag used in struct onoff_service_transitions.
|
* @brief Flag used in struct onoff_manager_transitions.
|
||||||
*
|
*
|
||||||
* As with @ref ONOFF_SERVICE_START_SLEEPS but describing the
|
* As with @ref ONOFF_START_SLEEPS but describing the reset
|
||||||
* reset transition function.
|
* transition function.
|
||||||
*/
|
*/
|
||||||
ONOFF_SERVICE_RESET_SLEEPS = BIT(2),
|
ONOFF_RESET_SLEEPS = BIT(2),
|
||||||
|
|
||||||
/* Internal use. */
|
/* Internal use. */
|
||||||
ONOFF_SERVICE_HAS_ERROR = BIT(3),
|
ONOFF_HAS_ERROR = BIT(3),
|
||||||
|
|
||||||
/* This and higher bits reserved for internal use. */
|
/* This and higher bits reserved for internal use. */
|
||||||
ONOFF_SERVICE_INTERNAL_BASE = BIT(4),
|
ONOFF_INTERNAL_BASE = BIT(4),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ONOFF_SERVICE_START_SLEEPS __DEPRECATED_MACRO ONOFF_START_SLEEPS
|
||||||
|
#define ONOFF_SERVICE_STOP_SLEEPS __DEPRECATED_MACRO ONOFF_STOP_SLEEPS
|
||||||
|
#define ONOFF_SERVICE_RESET_SLEEPS __DEPRECATED_MACRO ONOFF_RESET_SLEEPS
|
||||||
|
#define ONOFF_SERVICE_HAS_ERROR __DEPRECATED_MACRO ONOFF_HAS_ERROR
|
||||||
|
#define ONOFF_SERVICE_INTERNAL_BASE __DEPRECATED_MACRO ONOFF_INTERNAL_BASE
|
||||||
|
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
struct onoff_service;
|
struct onoff_manager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Signature used to notify an on-off service that a transition
|
* @brief Signature used to notify an on-off manager that a transition
|
||||||
* has completed.
|
* has completed.
|
||||||
*
|
*
|
||||||
* Functions of this type are passed to service-specific transition
|
* Functions of this type are passed to service-specific transition
|
||||||
* functions to be used to report the completion of the operation.
|
* functions to be used to report the completion of the operation.
|
||||||
* The functions may be invoked from any context.
|
* The functions may be invoked from any context.
|
||||||
*
|
*
|
||||||
* @param srv the service for which transition was requested.
|
* @param mgr the manager for which transition was requested.
|
||||||
*
|
*
|
||||||
* @param res the result of the transition. This shall be
|
* @param res the result of the transition. This shall be
|
||||||
* non-negative on success, or a negative error code. If an error is
|
* non-negative on success, or a negative error code. If an error is
|
||||||
* indicated the service shall enter an error state.
|
* indicated the service shall enter an error state.
|
||||||
*/
|
*/
|
||||||
typedef void (*onoff_service_notify_fn)(struct onoff_service *srv,
|
typedef void (*onoff_notify_fn)(struct onoff_manager *mgr,
|
||||||
int res);
|
int res);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Signature used by service implementations to effect a
|
* @brief Signature used by service implementations to effect a
|
||||||
|
@ -89,10 +96,10 @@ typedef void (*onoff_service_notify_fn)(struct onoff_service *srv,
|
||||||
*
|
*
|
||||||
* The stop function will be called only from the on state.
|
* The stop function will be called only from the on state.
|
||||||
*
|
*
|
||||||
* The reset function may be called only when
|
* The reset function may be called only when onoff_has_error()
|
||||||
* onoff_service_has_error() returns true.
|
* returns true.
|
||||||
*
|
*
|
||||||
* @param srv the service for which transition was requested.
|
* @param mgr the manager for which transition was requested.
|
||||||
*
|
*
|
||||||
* @param notify the function to be invoked when the transition has
|
* @param notify the function to be invoked when the transition has
|
||||||
* completed. The callee shall capture this parameter to notify on
|
* completed. The callee shall capture this parameter to notify on
|
||||||
|
@ -100,41 +107,40 @@ typedef void (*onoff_service_notify_fn)(struct onoff_service *srv,
|
||||||
* asynchronous, notify shall be invoked before the transition
|
* asynchronous, notify shall be invoked before the transition
|
||||||
* function returns.
|
* function returns.
|
||||||
*/
|
*/
|
||||||
typedef void (*onoff_service_transition_fn)(struct onoff_service *srv,
|
typedef void (*onoff_transition_fn)(struct onoff_manager *mgr,
|
||||||
onoff_service_notify_fn notify);
|
onoff_notify_fn notify);
|
||||||
|
|
||||||
/** @brief On-off service transition functions. */
|
/** @brief On-off service transition functions. */
|
||||||
struct onoff_service_transitions {
|
struct onoff_transitions {
|
||||||
/* Function to invoke to transition the service to on. */
|
/* Function to invoke to transition the service to on. */
|
||||||
onoff_service_transition_fn start;
|
onoff_transition_fn start;
|
||||||
|
|
||||||
/* Function to invoke to transition the service to off. */
|
/* Function to invoke to transition the service to off. */
|
||||||
onoff_service_transition_fn stop;
|
onoff_transition_fn stop;
|
||||||
|
|
||||||
/* Function to force the service state to reset, where supported. */
|
/* Function to force the service state to reset, where supported. */
|
||||||
onoff_service_transition_fn reset;
|
onoff_transition_fn reset;
|
||||||
|
|
||||||
/* Flags identifying transition function capabilities. */
|
/* Flags identifying transition function capabilities. */
|
||||||
u8_t flags;
|
u8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief State associated with an on-off service.
|
* @brief State associated with an on-off manager.
|
||||||
*
|
*
|
||||||
* No fields in this structure are intended for use by service
|
* No fields in this structure are intended for use by service
|
||||||
* providers or clients. The state is to be initialized once, using
|
* providers or clients. The state is to be initialized once, using
|
||||||
* onoff_service_init(), when the service provider is initialized.
|
* onoff_manager_init(), when the service provider is initialized. In
|
||||||
* In case of error it may be reset through the
|
* case of error it may be reset through the onoff_reset() API.
|
||||||
* onoff_service_reset() API.
|
|
||||||
*/
|
*/
|
||||||
struct onoff_service {
|
struct onoff_manager {
|
||||||
/* List of clients waiting for completion of reset or
|
/* List of clients waiting for completion of reset or
|
||||||
* transition to on.
|
* transition to on.
|
||||||
*/
|
*/
|
||||||
sys_slist_t clients;
|
sys_slist_t clients;
|
||||||
|
|
||||||
/* Transition functions. */
|
/* Transition functions. */
|
||||||
const struct onoff_service_transitions *transitions;
|
const struct onoff_transitions *transitions;
|
||||||
|
|
||||||
/* Mutex protection for flags, clients, releaser, and refs. */
|
/* Mutex protection for flags, clients, releaser, and refs. */
|
||||||
struct k_spinlock lock;
|
struct k_spinlock lock;
|
||||||
|
@ -149,7 +155,7 @@ struct onoff_service {
|
||||||
u16_t refs;
|
u16_t refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Initializer of transitions structure.
|
/** @brief Initializer for a onoff_transitions object.
|
||||||
*
|
*
|
||||||
* @param _start a function used to transition from off to on state.
|
* @param _start a function used to transition from off to on state.
|
||||||
*
|
*
|
||||||
|
@ -158,21 +164,30 @@ struct onoff_service {
|
||||||
* @param _reset a function used to clear errors and force the service to an off
|
* @param _reset a function used to clear errors and force the service to an off
|
||||||
* state. Can be null.
|
* state. Can be null.
|
||||||
*
|
*
|
||||||
* @param _flags any or all of the flags from enum onoff_service_flags.
|
* @param _flags any or all of the flags from enum onoff_manager_flags.
|
||||||
*/
|
*/
|
||||||
#define ONOFF_SERVICE_TRANSITIONS_INITIALIZER(_start, _stop, _reset, _flags) { \
|
#define ONOFF_TRANSITIONS_INITIALIZER(_start, _stop, _reset, _flags) { \
|
||||||
.start = _start, \
|
.start = _start, \
|
||||||
.stop = _stop, \
|
.stop = _stop, \
|
||||||
.reset = _reset, \
|
.reset = _reset, \
|
||||||
.flags = _flags, \
|
.flags = _flags, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ONOFF_SERVICE_TRANSITIONS_INITIALIZER(_start, _stop, _reset, _flags) \
|
||||||
|
__DEPRECATED_MACRO \
|
||||||
|
ONOFF_TRANSISTIONS_INITIALIZER(_start, _stop, _reset, _flags)
|
||||||
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
#define ONOFF_SERVICE_INITIALIZER(_transitions) { \
|
#define ONOFF_MANAGER_INITIALIZER(_transitions) { \
|
||||||
.transitions = _transitions, \
|
.transitions = _transitions, \
|
||||||
.flags = (_transitions)->flags, \
|
.flags = (_transitions)->flags, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ONOFF_SERVICE_INITIALIZER(_transitions) \
|
||||||
|
__DEPRECATED_MACRO \
|
||||||
|
ONOFF_MANAGER_INITIALIZER(_transitions)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize an on-off service to off state.
|
* @brief Initialize an on-off service to off state.
|
||||||
*
|
*
|
||||||
|
@ -182,7 +197,7 @@ struct onoff_service {
|
||||||
*
|
*
|
||||||
* This function should never be invoked by clients of an on-off service.
|
* This function should never be invoked by clients of an on-off service.
|
||||||
*
|
*
|
||||||
* @param srv the service definition object to be initialized.
|
* @param mgr the manager definition object to be initialized.
|
||||||
*
|
*
|
||||||
* @param transitions A structure with transition functions. Structure must be
|
* @param transitions A structure with transition functions. Structure must be
|
||||||
* persistent as it is used by the service.
|
* persistent as it is used by the service.
|
||||||
|
@ -190,8 +205,8 @@ struct onoff_service {
|
||||||
* @retval 0 on success
|
* @retval 0 on success
|
||||||
* @retval -EINVAL if start, stop, or flags are invalid
|
* @retval -EINVAL if start, stop, or flags are invalid
|
||||||
*/
|
*/
|
||||||
int onoff_service_init(struct onoff_service *srv,
|
int onoff_manager_init(struct onoff_manager *mgr,
|
||||||
const struct onoff_service_transitions *transitions);
|
const struct onoff_transitions *transitions);
|
||||||
|
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
struct onoff_client;
|
struct onoff_client;
|
||||||
|
@ -204,7 +219,7 @@ struct onoff_client;
|
||||||
* pre-kernel, ISR, or cooperative or pre-emptible threads.
|
* pre-kernel, ISR, or cooperative or pre-emptible threads.
|
||||||
* Compatible functions must be isr-callable and non-suspendable.
|
* Compatible functions must be isr-callable and non-suspendable.
|
||||||
*
|
*
|
||||||
* @param srv the service for which the operation was initiated.
|
* @param mgr the manager for which the operation was initiated.
|
||||||
*
|
*
|
||||||
* @param cli the client structure passed to the function that
|
* @param cli the client structure passed to the function that
|
||||||
* initiated the operation.
|
* initiated the operation.
|
||||||
|
@ -216,7 +231,7 @@ struct onoff_client;
|
||||||
* service-specific, but the value shall be non-negative if the
|
* service-specific, but the value shall be non-negative if the
|
||||||
* operation succeeded, and negative if the operation failed.
|
* operation succeeded, and negative if the operation failed.
|
||||||
*/
|
*/
|
||||||
typedef void (*onoff_client_callback)(struct onoff_service *srv,
|
typedef void (*onoff_client_callback)(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli,
|
struct onoff_client *cli,
|
||||||
void *user_data,
|
void *user_data,
|
||||||
int res);
|
int res);
|
||||||
|
@ -232,11 +247,7 @@ typedef void (*onoff_client_callback)(struct onoff_service *srv,
|
||||||
* when a pointer to the object is passed to any on-off service
|
* when a pointer to the object is passed to any on-off service
|
||||||
* function. While the service provider controls the object the
|
* function. While the service provider controls the object the
|
||||||
* client must not change any object fields. Control reverts to the
|
* client must not change any object fields. Control reverts to the
|
||||||
* client:
|
* client concurrent with release of the owned sys_notify structure.
|
||||||
* * if the call to the service API returns an error;
|
|
||||||
* * if the call to the service API succeeds for a no-wait operation;
|
|
||||||
* * when operation completion is posted (signalled or callback
|
|
||||||
* invoked).
|
|
||||||
*
|
*
|
||||||
* After control has reverted to the client the state object must be
|
* After control has reverted to the client the state object must be
|
||||||
* reinitialized for the next operation.
|
* reinitialized for the next operation.
|
||||||
|
@ -383,7 +394,7 @@ static inline void onoff_client_init_callback(struct onoff_client *cli,
|
||||||
* transition to on can sleep, the transition cannot be started and
|
* transition to on can sleep, the transition cannot be started and
|
||||||
* the request will fail with `-EWOULDBLOCK`.
|
* the request will fail with `-EWOULDBLOCK`.
|
||||||
*
|
*
|
||||||
* @param srv the service that will be used.
|
* @param mgr the manager that will be used.
|
||||||
*
|
*
|
||||||
* @param cli a non-null pointer to client state providing
|
* @param cli a non-null pointer to client state providing
|
||||||
* instructions on synchronous expectations and how to notify the
|
* instructions on synchronous expectations and how to notify the
|
||||||
|
@ -399,7 +410,7 @@ static inline void onoff_client_init_callback(struct onoff_client *cli,
|
||||||
* context and successful initiation could result in an attempt to
|
* context and successful initiation could result in an attempt to
|
||||||
* make the calling thread sleep.
|
* make the calling thread sleep.
|
||||||
*/
|
*/
|
||||||
int onoff_request(struct onoff_service *srv,
|
int onoff_request(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli);
|
struct onoff_client *cli);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -415,7 +426,7 @@ int onoff_request(struct onoff_service *srv,
|
||||||
* actual release fails. Always check the operation completion
|
* actual release fails. Always check the operation completion
|
||||||
* result.
|
* result.
|
||||||
*
|
*
|
||||||
* @param srv the service that will be used.
|
* @param mgr the manager that will be used.
|
||||||
*
|
*
|
||||||
* @param cli a non-null pointer to client state providing
|
* @param cli a non-null pointer to client state providing
|
||||||
* instructions on how to notify the client when release completes.
|
* instructions on how to notify the client when release completes.
|
||||||
|
@ -431,7 +442,7 @@ int onoff_request(struct onoff_service *srv,
|
||||||
* to off
|
* to off
|
||||||
* @retval -EBUSY if the service is transitioning to on
|
* @retval -EBUSY if the service is transitioning to on
|
||||||
*/
|
*/
|
||||||
int onoff_release(struct onoff_service *srv,
|
int onoff_release(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli);
|
struct onoff_client *cli);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -439,13 +450,17 @@ int onoff_release(struct onoff_service *srv,
|
||||||
*
|
*
|
||||||
* This function can be used to determine whether the service has
|
* This function can be used to determine whether the service has
|
||||||
* recorded an error. Errors may be cleared by invoking
|
* recorded an error. Errors may be cleared by invoking
|
||||||
* onoff_service_reset().
|
* onoff_reset().
|
||||||
|
*
|
||||||
|
* This is an unlocked convenience function suitable for use only when
|
||||||
|
* it is known that no other process might invoke an operation that
|
||||||
|
* transitions the service between an error and non-error state.
|
||||||
*
|
*
|
||||||
* @return true if and only if the service has an uncleared error.
|
* @return true if and only if the service has an uncleared error.
|
||||||
*/
|
*/
|
||||||
static inline bool onoff_service_has_error(const struct onoff_service *srv)
|
static inline bool onoff_has_error(const struct onoff_manager *mgr)
|
||||||
{
|
{
|
||||||
return (srv->flags & ONOFF_SERVICE_HAS_ERROR) != 0;
|
return (mgr->flags & ONOFF_HAS_ERROR) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -453,7 +468,7 @@ static inline bool onoff_service_has_error(const struct onoff_service *srv)
|
||||||
* state.
|
* state.
|
||||||
*
|
*
|
||||||
* A service can only be reset when it is in an error state as
|
* A service can only be reset when it is in an error state as
|
||||||
* indicated by onoff_service_has_error().
|
* indicated by onoff_has_error().
|
||||||
*
|
*
|
||||||
* The return value indicates the success or failure of an attempt to
|
* The return value indicates the success or failure of an attempt to
|
||||||
* initiate an operation to reset the resource. If initiation of the
|
* initiate an operation to reset the resource. If initiation of the
|
||||||
|
@ -465,15 +480,12 @@ static inline bool onoff_service_has_error(const struct onoff_service *srv)
|
||||||
* Note that the call to this function may succeed in a case where the
|
* Note that the call to this function may succeed in a case where the
|
||||||
* actual reset fails. Always check the operation completion result.
|
* actual reset fails. Always check the operation completion result.
|
||||||
*
|
*
|
||||||
* This function is blocking if the reset transition is blocking,
|
|
||||||
* unless client notification specifies no-wait.
|
|
||||||
*
|
|
||||||
* @note Due to the conditions on state transition all incomplete
|
* @note Due to the conditions on state transition all incomplete
|
||||||
* asynchronous operations will have been informed of the error when
|
* asynchronous operations will have been informed of the error when
|
||||||
* it occurred. There need be no concern about dangling requests left
|
* it occurred. There need be no concern about dangling requests left
|
||||||
* after a reset completes.
|
* after a reset completes.
|
||||||
*
|
*
|
||||||
* @param srv the service to be reset.
|
* @param mgr the manager to be reset.
|
||||||
*
|
*
|
||||||
* @param cli pointer to client state, including instructions on how
|
* @param cli pointer to client state, including instructions on how
|
||||||
* to notify the client when reset completes. Behavior is undefined
|
* to notify the client when reset completes. Behavior is undefined
|
||||||
|
@ -481,12 +493,12 @@ static inline bool onoff_service_has_error(const struct onoff_service *srv)
|
||||||
* operation.
|
* operation.
|
||||||
*
|
*
|
||||||
* @retval 0 on success
|
* @retval 0 on success
|
||||||
* @retval -ENOTSUP if reset is not supported
|
* @retval -ENOTSUP if reset is not supported by the service.
|
||||||
* @retval -EINVAL if the parameters are invalid, or if the service
|
* @retval -EINVAL if the parameters are invalid.
|
||||||
* @retval -EALREADY if the service does not have a recorded error
|
* @retval -EALREADY if the service does not have a recorded error.
|
||||||
*/
|
*/
|
||||||
int onoff_service_reset(struct onoff_service *srv,
|
int onoff_reset(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli);
|
struct onoff_client *cli);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attempt to cancel an in-progress client operation.
|
* @brief Attempt to cancel an in-progress client operation.
|
||||||
|
@ -511,7 +523,7 @@ int onoff_service_reset(struct onoff_service *srv,
|
||||||
* If the cancellation fails the service retains control of the client
|
* If the cancellation fails the service retains control of the client
|
||||||
* object, and the client must wait for operation completion.
|
* object, and the client must wait for operation completion.
|
||||||
*
|
*
|
||||||
* @param srv the service for which an operation is to be cancelled.
|
* @param mgr the manager for which an operation is to be cancelled.
|
||||||
*
|
*
|
||||||
* @param cli a pointer to the same client state that was provided
|
* @param cli a pointer to the same client state that was provided
|
||||||
* when the operation to be cancelled was issued. If the cancellation
|
* when the operation to be cancelled was issued. If the cancellation
|
||||||
|
@ -530,7 +542,7 @@ int onoff_service_reset(struct onoff_service *srv,
|
||||||
* likely indicates that the operation and client notification had
|
* likely indicates that the operation and client notification had
|
||||||
* already completed.
|
* already completed.
|
||||||
*/
|
*/
|
||||||
int onoff_cancel(struct onoff_service *srv,
|
int onoff_cancel(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli);
|
struct onoff_client *cli);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
255
lib/os/onoff.c
255
lib/os/onoff.c
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -7,33 +8,32 @@
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <sys/onoff.h>
|
#include <sys/onoff.h>
|
||||||
|
|
||||||
|
#define SERVICE_CONFIG_FLAGS \
|
||||||
#define SERVICE_CONFIG_FLAGS \
|
(ONOFF_START_SLEEPS \
|
||||||
(ONOFF_SERVICE_START_SLEEPS \
|
| ONOFF_STOP_SLEEPS \
|
||||||
| ONOFF_SERVICE_STOP_SLEEPS \
|
| ONOFF_RESET_SLEEPS)
|
||||||
| ONOFF_SERVICE_RESET_SLEEPS)
|
|
||||||
|
|
||||||
#define SERVICE_REFS_MAX UINT16_MAX
|
#define SERVICE_REFS_MAX UINT16_MAX
|
||||||
|
|
||||||
#define SERVICE_STATE_OFF 0
|
#define ST_OFF 0
|
||||||
#define SERVICE_STATE_ON ONOFF_SERVICE_INTERNAL_BASE
|
#define ST_ON ONOFF_INTERNAL_BASE
|
||||||
#define SERVICE_STATE_TRANSITION (ONOFF_SERVICE_INTERNAL_BASE << 1)
|
#define ST_TRANSITION (ONOFF_INTERNAL_BASE << 1)
|
||||||
#define SERVICE_STATE_TO_ON (SERVICE_STATE_TRANSITION | SERVICE_STATE_ON)
|
#define ST_TO_ON (ST_TRANSITION | ST_ON)
|
||||||
#define SERVICE_STATE_TO_OFF (SERVICE_STATE_TRANSITION | SERVICE_STATE_OFF)
|
#define ST_TO_OFF (ST_TRANSITION | ST_OFF)
|
||||||
|
|
||||||
#define SERVICE_STATE_MASK (SERVICE_STATE_ON | SERVICE_STATE_TRANSITION)
|
#define ST_MASK (ST_ON | ST_TRANSITION)
|
||||||
|
|
||||||
static void set_service_state(struct onoff_service *srv,
|
static void set_service_state(struct onoff_manager *mgr,
|
||||||
u32_t state)
|
u32_t state)
|
||||||
{
|
{
|
||||||
srv->flags &= ~SERVICE_STATE_MASK;
|
mgr->flags &= ~ST_MASK;
|
||||||
srv->flags |= (state & SERVICE_STATE_MASK);
|
mgr->flags |= (state & ST_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int validate_args(const struct onoff_service *srv,
|
static int validate_args(const struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli)
|
struct onoff_client *cli)
|
||||||
{
|
{
|
||||||
if ((srv == NULL) || (cli == NULL)) {
|
if ((mgr == NULL) || (cli == NULL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ static int validate_args(const struct onoff_service *srv,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int onoff_service_init(struct onoff_service *srv,
|
int onoff_manager_init(struct onoff_manager *mgr,
|
||||||
const struct onoff_service_transitions *transitions)
|
const struct onoff_transitions *transitions)
|
||||||
{
|
{
|
||||||
if (transitions->flags & ~SERVICE_CONFIG_FLAGS) {
|
if (transitions->flags & ~SERVICE_CONFIG_FLAGS) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -58,24 +58,25 @@ int onoff_service_init(struct onoff_service *srv,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*srv = (struct onoff_service)ONOFF_SERVICE_INITIALIZER(transitions);
|
*mgr = (struct onoff_manager)ONOFF_MANAGER_INITIALIZER(transitions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_one(struct onoff_service *srv,
|
static void notify_one(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli,
|
struct onoff_client *cli,
|
||||||
int res)
|
int res)
|
||||||
{
|
{
|
||||||
|
void *ud = cli->user_data;
|
||||||
onoff_client_callback cb =
|
onoff_client_callback cb =
|
||||||
(onoff_client_callback)sys_notify_finalize(&cli->notify, res);
|
(onoff_client_callback)sys_notify_finalize(&cli->notify, res);
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
cb(srv, cli, cli->user_data, res);
|
cb(mgr, cli, ud, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_all(struct onoff_service *srv,
|
static void notify_all(struct onoff_manager *mgr,
|
||||||
sys_slist_t *list,
|
sys_slist_t *list,
|
||||||
int res)
|
int res)
|
||||||
{
|
{
|
||||||
|
@ -86,18 +87,18 @@ static void notify_all(struct onoff_service *srv,
|
||||||
struct onoff_client,
|
struct onoff_client,
|
||||||
node);
|
node);
|
||||||
|
|
||||||
notify_one(srv, cli, res);
|
notify_one(mgr, cli, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onoff_start_notify(struct onoff_service *srv,
|
static void onoff_start_notify(struct onoff_manager *mgr,
|
||||||
int res)
|
int res)
|
||||||
{
|
{
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
sys_slist_t clients = srv->clients;
|
sys_slist_t clients = mgr->clients;
|
||||||
|
|
||||||
/* Can't have a queued releaser during start */
|
/* Can't have a queued releaser during start */
|
||||||
__ASSERT_NO_MSG(srv->releaser == NULL);
|
__ASSERT_NO_MSG(mgr->releaser == NULL);
|
||||||
|
|
||||||
/* If the start failed log an error and leave the rest of the
|
/* If the start failed log an error and leave the rest of the
|
||||||
* state in place for diagnostics.
|
* state in place for diagnostics.
|
||||||
|
@ -110,13 +111,13 @@ static void onoff_start_notify(struct onoff_service *srv,
|
||||||
* clients of operation completion.
|
* clients of operation completion.
|
||||||
*/
|
*/
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
srv->flags &= ~SERVICE_STATE_TRANSITION;
|
mgr->flags &= ~ST_TRANSITION;
|
||||||
srv->flags |= ONOFF_SERVICE_HAS_ERROR;
|
mgr->flags |= ONOFF_HAS_ERROR;
|
||||||
} else {
|
} else {
|
||||||
sys_snode_t *node;
|
sys_snode_t *node;
|
||||||
unsigned int refs = 0U;
|
unsigned int refs = 0U;
|
||||||
|
|
||||||
set_service_state(srv, SERVICE_STATE_ON);
|
set_service_state(mgr, ST_ON);
|
||||||
|
|
||||||
SYS_SLIST_FOR_EACH_NODE(&clients, node) {
|
SYS_SLIST_FOR_EACH_NODE(&clients, node) {
|
||||||
refs += 1U;
|
refs += 1U;
|
||||||
|
@ -125,78 +126,78 @@ static void onoff_start_notify(struct onoff_service *srv,
|
||||||
/* Update the reference count, or fail if the count
|
/* Update the reference count, or fail if the count
|
||||||
* would overflow.
|
* would overflow.
|
||||||
*/
|
*/
|
||||||
if (srv->refs > (SERVICE_REFS_MAX - refs)) {
|
if (mgr->refs > (SERVICE_REFS_MAX - refs)) {
|
||||||
srv->flags |= ONOFF_SERVICE_HAS_ERROR;
|
mgr->flags |= ONOFF_HAS_ERROR;
|
||||||
} else {
|
} else {
|
||||||
srv->refs += refs;
|
mgr->refs += refs;
|
||||||
}
|
}
|
||||||
__ASSERT_NO_MSG(srv->refs > 0U);
|
__ASSERT_NO_MSG(mgr->refs > 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&srv->clients);
|
sys_slist_init(&mgr->clients);
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
notify_all(srv, &clients, res);
|
notify_all(mgr, &clients, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int onoff_request(struct onoff_service *srv,
|
int onoff_request(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli)
|
struct onoff_client *cli)
|
||||||
{
|
{
|
||||||
bool add_client = false; /* add client to pending list */
|
bool add_client = false; /* add client to pending list */
|
||||||
bool start = false; /* invoke start transition */
|
bool start = false; /* invoke start transition */
|
||||||
bool notify = false; /* do client notification */
|
bool notify = false; /* do client notification */
|
||||||
int rv = validate_args(srv, cli);
|
int rv = validate_args(mgr, cli);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
|
|
||||||
if ((srv->flags & ONOFF_SERVICE_HAS_ERROR) != 0) {
|
if ((mgr->flags & ONOFF_HAS_ERROR) != 0) {
|
||||||
rv = -EIO;
|
rv = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reject if this would overflow the reference count. */
|
/* Reject if this would overflow the reference count. */
|
||||||
if (srv->refs == SERVICE_REFS_MAX) {
|
if (mgr->refs == SERVICE_REFS_MAX) {
|
||||||
rv = -EAGAIN;
|
rv = -EAGAIN;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_t state = srv->flags & SERVICE_STATE_MASK;
|
u32_t state = mgr->flags & ST_MASK;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SERVICE_STATE_TO_OFF:
|
case ST_TO_OFF:
|
||||||
/* Queue to start after release */
|
/* Queue to start after release */
|
||||||
__ASSERT_NO_MSG(srv->releaser != NULL);
|
__ASSERT_NO_MSG(mgr->releaser != NULL);
|
||||||
add_client = true;
|
add_client = true;
|
||||||
rv = 3;
|
rv = 3;
|
||||||
break;
|
break;
|
||||||
case SERVICE_STATE_OFF:
|
case ST_OFF:
|
||||||
/* Reject if in a non-thread context and start could
|
/* Reject if in a non-thread context and start could
|
||||||
* wait.
|
* wait.
|
||||||
*/
|
*/
|
||||||
if ((k_is_in_isr() || k_is_pre_kernel())
|
if ((k_is_in_isr() || k_is_pre_kernel())
|
||||||
&& ((srv->flags & ONOFF_SERVICE_START_SLEEPS) != 0U)) {
|
&& ((mgr->flags & ONOFF_START_SLEEPS) != 0U)) {
|
||||||
rv = -EWOULDBLOCK;
|
rv = -EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start with first request while off */
|
/* Start with first request while off */
|
||||||
__ASSERT_NO_MSG(srv->refs == 0);
|
__ASSERT_NO_MSG(mgr->refs == 0);
|
||||||
set_service_state(srv, SERVICE_STATE_TO_ON);
|
set_service_state(mgr, ST_TO_ON);
|
||||||
start = true;
|
start = true;
|
||||||
add_client = true;
|
add_client = true;
|
||||||
rv = 2;
|
rv = 2;
|
||||||
break;
|
break;
|
||||||
case SERVICE_STATE_TO_ON:
|
case ST_TO_ON:
|
||||||
/* Already starting, just queue it */
|
/* Already starting, just queue it */
|
||||||
add_client = true;
|
add_client = true;
|
||||||
rv = 1;
|
rv = 1;
|
||||||
break;
|
break;
|
||||||
case SERVICE_STATE_ON:
|
case ST_ON:
|
||||||
/* Just increment the reference count */
|
/* Just increment the reference count */
|
||||||
notify = true;
|
notify = true;
|
||||||
break;
|
break;
|
||||||
|
@ -207,32 +208,32 @@ int onoff_request(struct onoff_service *srv,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (add_client) {
|
if (add_client) {
|
||||||
sys_slist_append(&srv->clients, &cli->node);
|
sys_slist_append(&mgr->clients, &cli->node);
|
||||||
} else if (notify) {
|
} else if (notify) {
|
||||||
srv->refs += 1;
|
mgr->refs += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
__ASSERT_NO_MSG(srv->transitions->start != NULL);
|
__ASSERT_NO_MSG(mgr->transitions->start != NULL);
|
||||||
srv->transitions->start(srv, onoff_start_notify);
|
mgr->transitions->start(mgr, onoff_start_notify);
|
||||||
} else if (notify) {
|
} else if (notify) {
|
||||||
notify_one(srv, cli, 0);
|
notify_one(mgr, cli, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onoff_stop_notify(struct onoff_service *srv,
|
static void onoff_stop_notify(struct onoff_manager *mgr,
|
||||||
int res)
|
int res)
|
||||||
{
|
{
|
||||||
bool notify_clients = false;
|
bool notify_clients = false;
|
||||||
int client_res = res;
|
int client_res = res;
|
||||||
bool start = false;
|
bool start = false;
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
sys_slist_t clients = srv->clients;
|
sys_slist_t clients = mgr->clients;
|
||||||
struct onoff_client *releaser = srv->releaser;
|
struct onoff_client *releaser = mgr->releaser;
|
||||||
|
|
||||||
/* If the stop operation failed log an error and leave the
|
/* If the stop operation failed log an error and leave the
|
||||||
* rest of the state in place.
|
* rest of the state in place.
|
||||||
|
@ -244,72 +245,72 @@ static void onoff_stop_notify(struct onoff_service *srv,
|
||||||
* waiting clients of operation completion.
|
* waiting clients of operation completion.
|
||||||
*/
|
*/
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
srv->flags &= ~SERVICE_STATE_TRANSITION;
|
mgr->flags &= ~ST_TRANSITION;
|
||||||
srv->flags |= ONOFF_SERVICE_HAS_ERROR;
|
mgr->flags |= ONOFF_HAS_ERROR;
|
||||||
notify_clients = true;
|
notify_clients = true;
|
||||||
} else if (sys_slist_is_empty(&clients)) {
|
} else if (sys_slist_is_empty(&clients)) {
|
||||||
set_service_state(srv, SERVICE_STATE_OFF);
|
set_service_state(mgr, ST_OFF);
|
||||||
} else if ((k_is_in_isr() || k_is_pre_kernel())
|
} else if ((k_is_in_isr() || k_is_pre_kernel())
|
||||||
&& ((srv->flags & ONOFF_SERVICE_START_SLEEPS) != 0U)) {
|
&& ((mgr->flags & ONOFF_START_SLEEPS) != 0U)) {
|
||||||
set_service_state(srv, SERVICE_STATE_OFF);
|
set_service_state(mgr, ST_OFF);
|
||||||
notify_clients = true;
|
notify_clients = true;
|
||||||
client_res = -EWOULDBLOCK;
|
client_res = -EWOULDBLOCK;
|
||||||
} else {
|
} else {
|
||||||
set_service_state(srv, SERVICE_STATE_TO_ON);
|
set_service_state(mgr, ST_TO_ON);
|
||||||
start = true;
|
start = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
__ASSERT_NO_MSG(releaser);
|
__ASSERT_NO_MSG(releaser);
|
||||||
srv->refs -= 1U;
|
mgr->refs -= 1U;
|
||||||
srv->releaser = NULL;
|
mgr->releaser = NULL;
|
||||||
__ASSERT_NO_MSG(srv->refs == 0);
|
__ASSERT_NO_MSG(mgr->refs == 0);
|
||||||
|
|
||||||
/* Remove the clients if there was an error or a delayed start
|
/* Remove the clients if there was an error or a delayed start
|
||||||
* couldn't be initiated, because we're resolving their
|
* couldn't be initiated, because we're resolving their
|
||||||
* operation with an error.
|
* operation with an error.
|
||||||
*/
|
*/
|
||||||
if (notify_clients) {
|
if (notify_clients) {
|
||||||
sys_slist_init(&srv->clients);
|
sys_slist_init(&mgr->clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
/* Notify the releaser. If there was an error, notify any
|
/* Notify the releaser. If there was an error, notify any
|
||||||
* pending requests; otherwise if there are pending requests
|
* pending requests; otherwise if there are pending requests
|
||||||
* start the transition to ON.
|
* start the transition to ON.
|
||||||
*/
|
*/
|
||||||
notify_one(srv, releaser, res);
|
notify_one(mgr, releaser, res);
|
||||||
if (notify_clients) {
|
if (notify_clients) {
|
||||||
notify_all(srv, &clients, client_res);
|
notify_all(mgr, &clients, client_res);
|
||||||
} else if (start) {
|
} else if (start) {
|
||||||
srv->transitions->start(srv, onoff_start_notify);
|
mgr->transitions->start(mgr, onoff_start_notify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int onoff_release(struct onoff_service *srv,
|
int onoff_release(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli)
|
struct onoff_client *cli)
|
||||||
{
|
{
|
||||||
bool stop = false; /* invoke stop transition */
|
bool stop = false; /* invoke stop transition */
|
||||||
bool notify = false; /* do client notification */
|
bool notify = false; /* do client notification */
|
||||||
int rv = validate_args(srv, cli);
|
int rv = validate_args(mgr, cli);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
|
|
||||||
if ((srv->flags & ONOFF_SERVICE_HAS_ERROR) != 0) {
|
if ((mgr->flags & ONOFF_HAS_ERROR) != 0) {
|
||||||
rv = -EIO;
|
rv = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_t state = srv->flags & SERVICE_STATE_MASK;
|
u32_t state = mgr->flags & ST_MASK;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SERVICE_STATE_ON:
|
case ST_ON:
|
||||||
/* Stay on if release leaves a client. */
|
/* Stay on if release leaves a client. */
|
||||||
if (srv->refs > 1U) {
|
if (mgr->refs > 1U) {
|
||||||
notify = true;
|
notify = true;
|
||||||
rv = 1;
|
rv = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -319,23 +320,23 @@ int onoff_release(struct onoff_service *srv,
|
||||||
* wait
|
* wait
|
||||||
*/
|
*/
|
||||||
if ((k_is_in_isr() || k_is_pre_kernel())
|
if ((k_is_in_isr() || k_is_pre_kernel())
|
||||||
&& ((srv->flags & ONOFF_SERVICE_STOP_SLEEPS) != 0)) {
|
&& ((mgr->flags & ONOFF_STOP_SLEEPS) != 0)) {
|
||||||
rv = -EWOULDBLOCK;
|
rv = -EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop = true;
|
stop = true;
|
||||||
|
|
||||||
set_service_state(srv, SERVICE_STATE_TO_OFF);
|
set_service_state(mgr, ST_TO_OFF);
|
||||||
srv->releaser = cli;
|
mgr->releaser = cli;
|
||||||
rv = 2;
|
rv = 2;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SERVICE_STATE_TO_ON:
|
case ST_TO_ON:
|
||||||
rv = -EBUSY;
|
rv = -EBUSY;
|
||||||
break;
|
break;
|
||||||
case SERVICE_STATE_OFF:
|
case ST_OFF:
|
||||||
case SERVICE_STATE_TO_OFF:
|
case ST_TO_OFF:
|
||||||
rv = -EALREADY;
|
rv = -EALREADY;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -344,57 +345,57 @@ int onoff_release(struct onoff_service *srv,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (notify) {
|
if (notify) {
|
||||||
srv->refs -= 1U;
|
mgr->refs -= 1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
if (stop) {
|
if (stop) {
|
||||||
__ASSERT_NO_MSG(srv->transitions->stop != NULL);
|
__ASSERT_NO_MSG(mgr->transitions->stop != NULL);
|
||||||
srv->transitions->stop(srv, onoff_stop_notify);
|
mgr->transitions->stop(mgr, onoff_stop_notify);
|
||||||
} else if (notify) {
|
} else if (notify) {
|
||||||
notify_one(srv, cli, 0);
|
notify_one(mgr, cli, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onoff_reset_notify(struct onoff_service *srv,
|
static void onoff_reset_notify(struct onoff_manager *mgr,
|
||||||
int res)
|
int res)
|
||||||
{
|
{
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
sys_slist_t clients = srv->clients;
|
sys_slist_t clients = mgr->clients;
|
||||||
|
|
||||||
/* If the reset failed clear the transition flag but otherwise
|
/* If the reset failed clear the transition flag but otherwise
|
||||||
* leave the state unchanged.
|
* leave the state unchanged.
|
||||||
*
|
*
|
||||||
* If it was successful clear the reference count and all
|
* If it was successful clear the reference count and all
|
||||||
* flags except capability flags (sets to SERVICE_STATE_OFF).
|
* flags except capability flags (sets to ST_OFF).
|
||||||
*/
|
*/
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
srv->flags &= ~SERVICE_STATE_TRANSITION;
|
mgr->flags &= ~ST_TRANSITION;
|
||||||
} else {
|
} else {
|
||||||
__ASSERT_NO_MSG(srv->refs == 0U);
|
__ASSERT_NO_MSG(mgr->refs == 0U);
|
||||||
srv->refs = 0U;
|
mgr->refs = 0U;
|
||||||
srv->flags &= SERVICE_CONFIG_FLAGS;
|
mgr->flags &= SERVICE_CONFIG_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_slist_init(&srv->clients);
|
sys_slist_init(&mgr->clients);
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
notify_all(srv, &clients, res);
|
notify_all(mgr, &clients, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int onoff_service_reset(struct onoff_service *srv,
|
int onoff_reset(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli)
|
struct onoff_client *cli)
|
||||||
{
|
{
|
||||||
if (srv->transitions->reset == NULL) {
|
if (mgr->transitions->reset == NULL) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reset = false;
|
bool reset = false;
|
||||||
int rv = validate_args(srv, cli);
|
int rv = validate_args(mgr, cli);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -402,70 +403,70 @@ int onoff_service_reset(struct onoff_service *srv,
|
||||||
|
|
||||||
/* Reject if in a non-thread context and reset could wait. */
|
/* Reject if in a non-thread context and reset could wait. */
|
||||||
if ((k_is_in_isr() || k_is_pre_kernel())
|
if ((k_is_in_isr() || k_is_pre_kernel())
|
||||||
&& ((srv->flags & ONOFF_SERVICE_RESET_SLEEPS) != 0U)) {
|
&& ((mgr->flags & ONOFF_RESET_SLEEPS) != 0U)) {
|
||||||
return -EWOULDBLOCK;
|
return -EWOULDBLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
|
|
||||||
if ((srv->flags & ONOFF_SERVICE_HAS_ERROR) == 0) {
|
if ((mgr->flags & ONOFF_HAS_ERROR) == 0) {
|
||||||
rv = -EALREADY;
|
rv = -EALREADY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((srv->flags & SERVICE_STATE_TRANSITION) == 0) {
|
if ((mgr->flags & ST_TRANSITION) == 0) {
|
||||||
reset = true;
|
reset = true;
|
||||||
srv->flags |= SERVICE_STATE_TRANSITION;
|
mgr->flags |= ST_TRANSITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rv >= 0) {
|
if (rv >= 0) {
|
||||||
sys_slist_append(&srv->clients, &cli->node);
|
sys_slist_append(&mgr->clients, &cli->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
if (reset) {
|
if (reset) {
|
||||||
srv->transitions->reset(srv, onoff_reset_notify);
|
mgr->transitions->reset(mgr, onoff_reset_notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int onoff_cancel(struct onoff_service *srv,
|
int onoff_cancel(struct onoff_manager *mgr,
|
||||||
struct onoff_client *cli)
|
struct onoff_client *cli)
|
||||||
{
|
{
|
||||||
int rv = validate_args(srv, cli);
|
int rv = validate_args(mgr, cli);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = -EALREADY;
|
rv = -EALREADY;
|
||||||
k_spinlock_key_t key = k_spin_lock(&srv->lock);
|
k_spinlock_key_t key = k_spin_lock(&mgr->lock);
|
||||||
u32_t state = srv->flags & SERVICE_STATE_MASK;
|
u32_t state = mgr->flags & ST_MASK;
|
||||||
|
|
||||||
/* Can't remove the last client waiting for the in-progress
|
/* Can't remove the last client waiting for the in-progress
|
||||||
* transition, as there would be nobody to receive the
|
* transition, as there would be nobody to receive the
|
||||||
* completion notification, which might indicate a service
|
* completion notification, which might indicate a service
|
||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
if (sys_slist_find_and_remove(&srv->clients, &cli->node)) {
|
if (sys_slist_find_and_remove(&mgr->clients, &cli->node)) {
|
||||||
rv = 0;
|
rv = 0;
|
||||||
if (sys_slist_is_empty(&srv->clients)
|
if (sys_slist_is_empty(&mgr->clients)
|
||||||
&& (state != SERVICE_STATE_TO_OFF)) {
|
&& (state != ST_TO_OFF)) {
|
||||||
rv = -EWOULDBLOCK;
|
rv = -EWOULDBLOCK;
|
||||||
sys_slist_append(&srv->clients, &cli->node);
|
sys_slist_append(&mgr->clients, &cli->node);
|
||||||
}
|
}
|
||||||
} else if (srv->releaser == cli) {
|
} else if (mgr->releaser == cli) {
|
||||||
/* must be waiting for TO_OFF to complete */
|
/* must be waiting for TO_OFF to complete */
|
||||||
rv = -EWOULDBLOCK;
|
rv = -EWOULDBLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_spin_unlock(&srv->lock, key);
|
k_spin_unlock(&mgr->lock, key);
|
||||||
|
|
||||||
if (rv == 0) {
|
if (rv == 0) {
|
||||||
notify_one(srv, cli, -ECANCELED);
|
notify_one(mgr, cli, -ECANCELED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -11,7 +12,7 @@ static struct onoff_client spinwait_cli;
|
||||||
|
|
||||||
static int callback_res;
|
static int callback_res;
|
||||||
static void *callback_ud;
|
static void *callback_ud;
|
||||||
static void callback(struct onoff_service *srv,
|
static void callback(struct onoff_manager *srv,
|
||||||
struct onoff_client *cli,
|
struct onoff_client *cli,
|
||||||
void *ud,
|
void *ud,
|
||||||
int res)
|
int res)
|
||||||
|
@ -52,8 +53,8 @@ struct transit_state {
|
||||||
const char *tag;
|
const char *tag;
|
||||||
bool async;
|
bool async;
|
||||||
int retval;
|
int retval;
|
||||||
onoff_service_notify_fn notify;
|
onoff_notify_fn notify;
|
||||||
struct onoff_service *srv;
|
struct onoff_manager *srv;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void reset_transit_state(struct transit_state *tsp)
|
static void reset_transit_state(struct transit_state *tsp)
|
||||||
|
@ -64,8 +65,8 @@ static void reset_transit_state(struct transit_state *tsp)
|
||||||
tsp->srv = NULL;
|
tsp->srv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_transit(struct onoff_service *srv,
|
static void run_transit(struct onoff_manager *srv,
|
||||||
onoff_service_notify_fn notify,
|
onoff_notify_fn notify,
|
||||||
struct transit_state *tsp)
|
struct transit_state *tsp)
|
||||||
{
|
{
|
||||||
if (tsp->async) {
|
if (tsp->async) {
|
||||||
|
@ -99,7 +100,7 @@ static void isr_notify(struct k_timer *timer)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct isr_call_state {
|
struct isr_call_state {
|
||||||
struct onoff_service *srv;
|
struct onoff_manager *srv;
|
||||||
struct onoff_client *cli;
|
struct onoff_client *cli;
|
||||||
int result;
|
int result;
|
||||||
};
|
};
|
||||||
|
@ -124,15 +125,15 @@ static void isr_reset(struct k_timer *timer)
|
||||||
{
|
{
|
||||||
struct isr_call_state *rsp = k_timer_user_data_get(timer);
|
struct isr_call_state *rsp = k_timer_user_data_get(timer);
|
||||||
|
|
||||||
rsp->result = onoff_service_reset(rsp->srv, rsp->cli);
|
rsp->result = onoff_reset(rsp->srv, rsp->cli);
|
||||||
k_sem_give(&isr_sync);
|
k_sem_give(&isr_sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct transit_state start_state = {
|
static struct transit_state start_state = {
|
||||||
.tag = "start",
|
.tag = "start",
|
||||||
};
|
};
|
||||||
static void start(struct onoff_service *srv,
|
static void start(struct onoff_manager *srv,
|
||||||
onoff_service_notify_fn notify)
|
onoff_notify_fn notify)
|
||||||
{
|
{
|
||||||
run_transit(srv, notify, &start_state);
|
run_transit(srv, notify, &start_state);
|
||||||
}
|
}
|
||||||
|
@ -140,8 +141,8 @@ static void start(struct onoff_service *srv,
|
||||||
static struct transit_state stop_state = {
|
static struct transit_state stop_state = {
|
||||||
.tag = "stop",
|
.tag = "stop",
|
||||||
};
|
};
|
||||||
static void stop(struct onoff_service *srv,
|
static void stop(struct onoff_manager *srv,
|
||||||
onoff_service_notify_fn notify)
|
onoff_notify_fn notify)
|
||||||
{
|
{
|
||||||
run_transit(srv, notify, &stop_state);
|
run_transit(srv, notify, &stop_state);
|
||||||
}
|
}
|
||||||
|
@ -149,8 +150,8 @@ static void stop(struct onoff_service *srv,
|
||||||
static struct transit_state reset_state = {
|
static struct transit_state reset_state = {
|
||||||
.tag = "reset",
|
.tag = "reset",
|
||||||
};
|
};
|
||||||
static void reset(struct onoff_service *srv,
|
static void reset(struct onoff_manager *srv,
|
||||||
onoff_service_notify_fn notify)
|
onoff_notify_fn notify)
|
||||||
{
|
{
|
||||||
run_transit(srv, notify, &reset_state);
|
run_transit(srv, notify, &reset_state);
|
||||||
}
|
}
|
||||||
|
@ -166,39 +167,39 @@ static void clear_transit(void)
|
||||||
static void test_service_init_validation(void)
|
static void test_service_init_validation(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
const struct onoff_service_transitions null_transitions =
|
const struct onoff_transitions null_transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(NULL, NULL, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(NULL, NULL, NULL, 0);
|
||||||
const struct onoff_service_transitions start_transitions =
|
const struct onoff_transitions start_transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, NULL, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, NULL, NULL, 0);
|
||||||
const struct onoff_service_transitions stop_transitions =
|
const struct onoff_transitions stop_transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(NULL, stop, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(NULL, stop, NULL, 0);
|
||||||
struct onoff_service_transitions start_stop_transitions =
|
struct onoff_transitions start_stop_transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||||
const struct onoff_service_transitions all_transitions =
|
const struct onoff_transitions all_transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, reset,
|
||||||
ONOFF_SERVICE_START_SLEEPS);
|
ONOFF_START_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
|
|
||||||
rc = onoff_service_init(NULL, &null_transitions);
|
rc = onoff_manager_init(NULL, &null_transitions);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"init null srv %d", rc);
|
"init null srv %d", rc);
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &null_transitions);
|
rc = onoff_manager_init(&srv, &null_transitions);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"init null transit %d", rc);
|
"init null transit %d", rc);
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &start_transitions);
|
rc = onoff_manager_init(&srv, &start_transitions);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"init null stop %d", rc);
|
"init null stop %d", rc);
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &stop_transitions);
|
rc = onoff_manager_init(&srv, &stop_transitions);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"init null start %d", rc);
|
"init null start %d", rc);
|
||||||
|
|
||||||
start_stop_transitions.flags |= ONOFF_SERVICE_INTERNAL_BASE;
|
start_stop_transitions.flags |= ONOFF_INTERNAL_BASE;
|
||||||
rc = onoff_service_init(&srv, &start_stop_transitions);
|
rc = onoff_manager_init(&srv, &start_stop_transitions);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"init bad flags %d", rc);
|
"init bad flags %d", rc);
|
||||||
|
|
||||||
|
@ -206,7 +207,7 @@ static void test_service_init_validation(void)
|
||||||
zassert_false(sys_slist_is_empty(&srv.clients),
|
zassert_false(sys_slist_is_empty(&srv.clients),
|
||||||
"slist empty");
|
"slist empty");
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &all_transitions);
|
rc = onoff_manager_init(&srv, &all_transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"init good %d", rc);
|
"init good %d", rc);
|
||||||
zassert_equal(srv.transitions->start, start,
|
zassert_equal(srv.transitions->start, start,
|
||||||
|
@ -215,7 +216,7 @@ static void test_service_init_validation(void)
|
||||||
"init stop mismatch");
|
"init stop mismatch");
|
||||||
zassert_equal(srv.transitions->reset, reset,
|
zassert_equal(srv.transitions->reset, reset,
|
||||||
"init reset mismatch");
|
"init reset mismatch");
|
||||||
zassert_equal(srv.flags, ONOFF_SERVICE_START_SLEEPS,
|
zassert_equal(srv.flags, ONOFF_START_SLEEPS,
|
||||||
"init flags mismatch");
|
"init flags mismatch");
|
||||||
zassert_equal(srv.refs, 0,
|
zassert_equal(srv.refs, 0,
|
||||||
"init refs mismatch");
|
"init refs mismatch");
|
||||||
|
@ -262,11 +263,11 @@ static void test_client_init_validation(void)
|
||||||
static void test_validate_args(void)
|
static void test_validate_args(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig;
|
struct k_poll_signal sig;
|
||||||
struct onoff_client cli;
|
struct onoff_client cli;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
|
|
||||||
|
@ -274,7 +275,7 @@ static void test_validate_args(void)
|
||||||
* release, and reset; test it through the request API.
|
* release, and reset; test it through the request API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -340,30 +341,30 @@ static void test_validate_args(void)
|
||||||
static void test_reset(void)
|
static void test_reset(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig;
|
struct k_poll_signal sig;
|
||||||
struct onoff_client cli;
|
struct onoff_client cli;
|
||||||
unsigned int signalled = 0;
|
unsigned int signalled = 0;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL, 0);
|
||||||
struct onoff_service_transitions transitions_with_reset =
|
struct onoff_transitions transitions_with_reset =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
rc = onoff_service_reset(&srv, &cli);
|
rc = onoff_reset(&srv, &cli);
|
||||||
zassert_equal(rc, -ENOTSUP,
|
zassert_equal(rc, -ENOTSUP,
|
||||||
"reset: %d", rc);
|
"reset: %d", rc);
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions_with_reset);
|
rc = onoff_manager_init(&srv, &transitions_with_reset);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
rc = onoff_service_reset(&srv, NULL);
|
rc = onoff_reset(&srv, NULL);
|
||||||
zassert_equal(rc, -EINVAL,
|
zassert_equal(rc, -EINVAL,
|
||||||
"rst no cli");
|
"rst no cli");
|
||||||
|
|
||||||
|
@ -375,11 +376,11 @@ static void test_reset(void)
|
||||||
"reset req refs: %u", srv.refs);
|
"reset req refs: %u", srv.refs);
|
||||||
|
|
||||||
|
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
reset_state.retval = 57;
|
reset_state.retval = 57;
|
||||||
init_notify_sig(&cli, &sig);
|
init_notify_sig(&cli, &sig);
|
||||||
rc = onoff_service_reset(&srv, &cli);
|
rc = onoff_reset(&srv, &cli);
|
||||||
zassert_equal(rc, -EALREADY,
|
zassert_equal(rc, -EALREADY,
|
||||||
"reset: %d", rc);
|
"reset: %d", rc);
|
||||||
|
|
||||||
|
@ -390,7 +391,7 @@ static void test_reset(void)
|
||||||
"rel trigger: %d", rc);
|
"rel trigger: %d", rc);
|
||||||
zassert_equal(srv.refs, 0U,
|
zassert_equal(srv.refs, 0U,
|
||||||
"reset req refs: %u", srv.refs);
|
"reset req refs: %u", srv.refs);
|
||||||
zassert_true(onoff_service_has_error(&srv),
|
zassert_true(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
zassert_equal(cli_result(&cli), stop_state.retval,
|
zassert_equal(cli_result(&cli), stop_state.retval,
|
||||||
"cli result");
|
"cli result");
|
||||||
|
@ -405,24 +406,24 @@ static void test_reset(void)
|
||||||
|
|
||||||
reset_state.retval = -59;
|
reset_state.retval = -59;
|
||||||
init_notify_sig(&cli, &sig);
|
init_notify_sig(&cli, &sig);
|
||||||
rc = onoff_service_reset(&srv, &cli);
|
rc = onoff_reset(&srv, &cli);
|
||||||
zassert_equal(rc, 0U,
|
zassert_equal(rc, 0U,
|
||||||
"reset: %d", rc);
|
"reset: %d", rc);
|
||||||
zassert_equal(cli_result(&cli), reset_state.retval,
|
zassert_equal(cli_result(&cli), reset_state.retval,
|
||||||
"reset result");
|
"reset result");
|
||||||
zassert_equal(srv.refs, 0U,
|
zassert_equal(srv.refs, 0U,
|
||||||
"reset req refs: %u", srv.refs);
|
"reset req refs: %u", srv.refs);
|
||||||
zassert_true(onoff_service_has_error(&srv),
|
zassert_true(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
reset_state.retval = 62;
|
reset_state.retval = 62;
|
||||||
init_notify_sig(&cli, &sig);
|
init_notify_sig(&cli, &sig);
|
||||||
rc = onoff_service_reset(&srv, &cli);
|
rc = onoff_reset(&srv, &cli);
|
||||||
zassert_equal(rc, 0U,
|
zassert_equal(rc, 0U,
|
||||||
"reset: %d", rc);
|
"reset: %d", rc);
|
||||||
zassert_equal(cli_result(&cli), reset_state.retval,
|
zassert_equal(cli_result(&cli), reset_state.retval,
|
||||||
"reset result");
|
"reset result");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
signalled = 0;
|
signalled = 0;
|
||||||
|
@ -435,19 +436,19 @@ static void test_reset(void)
|
||||||
|
|
||||||
zassert_equal(srv.refs, 0U,
|
zassert_equal(srv.refs, 0U,
|
||||||
"reset req refs: %u", srv.refs);
|
"reset req refs: %u", srv.refs);
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
transitions_with_reset.flags |= ONOFF_SERVICE_RESET_SLEEPS;
|
transitions_with_reset.flags |= ONOFF_RESET_SLEEPS;
|
||||||
rc = onoff_service_init(&srv, &transitions_with_reset);
|
rc = onoff_manager_init(&srv, &transitions_with_reset);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
start_state.retval = -23;
|
start_state.retval = -23;
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
init_spinwait(&spinwait_cli);
|
init_spinwait(&spinwait_cli);
|
||||||
rc = onoff_request(&srv, &spinwait_cli);
|
rc = onoff_request(&srv, &spinwait_cli);
|
||||||
zassert_true(onoff_service_has_error(&srv),
|
zassert_true(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
struct isr_call_state isr_state = {
|
struct isr_call_state isr_state = {
|
||||||
|
@ -474,13 +475,13 @@ static void test_reset(void)
|
||||||
static void test_request(void)
|
static void test_request(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct onoff_service_transitions transitions =
|
struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -495,7 +496,7 @@ static void test_request(void)
|
||||||
|
|
||||||
/* Can't reset when no error present. */
|
/* Can't reset when no error present. */
|
||||||
init_spinwait(&spinwait_cli);
|
init_spinwait(&spinwait_cli);
|
||||||
rc = onoff_service_reset(&srv, &spinwait_cli);
|
rc = onoff_reset(&srv, &spinwait_cli);
|
||||||
zassert_equal(rc, -EALREADY,
|
zassert_equal(rc, -EALREADY,
|
||||||
"reset spin client");
|
"reset spin client");
|
||||||
|
|
||||||
|
@ -517,7 +518,7 @@ static void test_request(void)
|
||||||
"error release");
|
"error release");
|
||||||
zassert_equal(cli_result(&spinwait_cli), stop_state.retval,
|
zassert_equal(cli_result(&spinwait_cli), stop_state.retval,
|
||||||
"error retval");
|
"error retval");
|
||||||
zassert_true(onoff_service_has_error(&srv),
|
zassert_true(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* Can't request when error present. */
|
/* Can't request when error present. */
|
||||||
|
@ -537,10 +538,10 @@ static void test_request(void)
|
||||||
|
|
||||||
/* Clear the error */
|
/* Clear the error */
|
||||||
init_notify_sig(&cli, &sig);
|
init_notify_sig(&cli, &sig);
|
||||||
rc = onoff_service_reset(&srv, &cli);
|
rc = onoff_reset(&srv, &cli);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"reset");
|
"reset");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* Error on start */
|
/* Error on start */
|
||||||
|
@ -551,20 +552,20 @@ static void test_request(void)
|
||||||
"req with error");
|
"req with error");
|
||||||
zassert_equal(cli_result(&spinwait_cli), start_state.retval,
|
zassert_equal(cli_result(&spinwait_cli), start_state.retval,
|
||||||
"req with error");
|
"req with error");
|
||||||
zassert_true(onoff_service_has_error(&srv),
|
zassert_true(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* Clear the error */
|
/* Clear the error */
|
||||||
init_spinwait(&spinwait_cli);
|
init_spinwait(&spinwait_cli);
|
||||||
rc = onoff_service_reset(&srv, &spinwait_cli);
|
rc = onoff_reset(&srv, &spinwait_cli);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"reset");
|
"reset");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* Diagnose a no-wait delayed start */
|
/* Diagnose a no-wait delayed start */
|
||||||
transitions.flags |= ONOFF_SERVICE_START_SLEEPS;
|
transitions.flags |= ONOFF_START_SLEEPS;
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
start_state.async = true;
|
start_state.async = true;
|
||||||
|
@ -594,13 +595,13 @@ static void test_request(void)
|
||||||
static void test_sync(void)
|
static void test_sync(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, reset, 0);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -642,14 +643,15 @@ static void test_sync(void)
|
||||||
static void test_async(void)
|
static void test_async(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig[2];
|
struct k_poll_signal sig[2];
|
||||||
struct onoff_client cli[2];
|
struct onoff_client cli[2];
|
||||||
unsigned int signalled = 0;
|
unsigned int signalled = 0;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, reset,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, reset,
|
||||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
ONOFF_START_SLEEPS
|
||||||
|
| ONOFF_STOP_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.async = true;
|
start_state.async = true;
|
||||||
|
@ -657,7 +659,7 @@ static void test_async(void)
|
||||||
stop_state.async = true;
|
stop_state.async = true;
|
||||||
stop_state.retval = 17;
|
stop_state.retval = 17;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -837,19 +839,19 @@ static void test_async(void)
|
||||||
static void test_half_sync(void)
|
static void test_half_sync(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig;
|
struct k_poll_signal sig;
|
||||||
struct onoff_client cli;
|
struct onoff_client cli;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||||
ONOFF_SERVICE_STOP_SLEEPS);
|
ONOFF_STOP_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.retval = 23;
|
start_state.retval = 23;
|
||||||
stop_state.async = true;
|
stop_state.async = true;
|
||||||
stop_state.retval = 17;
|
stop_state.retval = 17;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -895,12 +897,13 @@ static void test_half_sync(void)
|
||||||
static void test_cancel_request_waits(void)
|
static void test_cancel_request_waits(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig;
|
struct k_poll_signal sig;
|
||||||
struct onoff_client cli;
|
struct onoff_client cli;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
ONOFF_START_SLEEPS
|
||||||
|
| ONOFF_STOP_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.async = true;
|
start_state.async = true;
|
||||||
|
@ -908,7 +911,7 @@ static void test_cancel_request_waits(void)
|
||||||
stop_state.async = true;
|
stop_state.async = true;
|
||||||
stop_state.retval = 31;
|
stop_state.retval = 31;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -936,7 +939,7 @@ static void test_cancel_request_waits(void)
|
||||||
"cancel failed: %d", rc);
|
"cancel failed: %d", rc);
|
||||||
zassert_equal(cli_result(&cli), -ECANCELED,
|
zassert_equal(cli_result(&cli), -ECANCELED,
|
||||||
"cancel notified");
|
"cancel notified");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* Not allowed to cancel the last pending start.
|
/* Not allowed to cancel the last pending start.
|
||||||
|
@ -944,7 +947,7 @@ static void test_cancel_request_waits(void)
|
||||||
rc = onoff_cancel(&srv, &spinwait_cli);
|
rc = onoff_cancel(&srv, &spinwait_cli);
|
||||||
zassert_equal(rc, -EWOULDBLOCK,
|
zassert_equal(rc, -EWOULDBLOCK,
|
||||||
"last cancel", rc);
|
"last cancel", rc);
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
zassert_equal(cli_result(&spinwait_cli), -EAGAIN,
|
zassert_equal(cli_result(&spinwait_cli), -EAGAIN,
|
||||||
"last request");
|
"last request");
|
||||||
|
@ -952,7 +955,7 @@ static void test_cancel_request_waits(void)
|
||||||
notify(&start_state);
|
notify(&start_state);
|
||||||
zassert_equal(cli_result(&spinwait_cli), start_state.retval,
|
zassert_equal(cli_result(&spinwait_cli), start_state.retval,
|
||||||
"last request");
|
"last request");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
|
|
||||||
|
@ -976,7 +979,7 @@ static void test_cancel_request_waits(void)
|
||||||
"restart cancel");
|
"restart cancel");
|
||||||
zassert_equal(cli_result(&spinwait_cli), -ECANCELED,
|
zassert_equal(cli_result(&spinwait_cli), -ECANCELED,
|
||||||
"restart cancel");
|
"restart cancel");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
zassert_equal(cli_result(&cli), -EAGAIN,
|
zassert_equal(cli_result(&cli), -EAGAIN,
|
||||||
|
@ -985,26 +988,26 @@ static void test_cancel_request_waits(void)
|
||||||
notify(&stop_state);
|
notify(&stop_state);
|
||||||
zassert_equal(cli_result(&cli), stop_state.retval,
|
zassert_equal(cli_result(&cli), stop_state.retval,
|
||||||
"released");
|
"released");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_cancel_request_ok(void)
|
static void test_cancel_request_ok(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
struct k_poll_signal sig;
|
struct k_poll_signal sig;
|
||||||
struct onoff_client cli;
|
struct onoff_client cli;
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||||
ONOFF_SERVICE_START_SLEEPS);
|
ONOFF_START_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.async = true;
|
start_state.async = true;
|
||||||
start_state.retval = 14;
|
start_state.retval = 14;
|
||||||
stop_state.retval = 31;
|
stop_state.retval = 31;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -1025,11 +1028,11 @@ static void test_cancel_request_ok(void)
|
||||||
notify(&start_state);
|
notify(&start_state);
|
||||||
zassert_equal(srv.refs, 1,
|
zassert_equal(srv.refs, 1,
|
||||||
"refs");
|
"refs");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
zassert_equal(cli_result(&cli), start_state.retval,
|
zassert_equal(cli_result(&cli), start_state.retval,
|
||||||
"cancel notified");
|
"cancel notified");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
/* You can "cancel" an request that isn't active */
|
/* You can "cancel" an request that isn't active */
|
||||||
|
@ -1047,14 +1050,15 @@ static void test_cancel_request_ok(void)
|
||||||
static void test_blocked_restart(void)
|
static void test_blocked_restart(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
struct onoff_manager srv;
|
||||||
unsigned int signalled = 0;
|
unsigned int signalled = 0;
|
||||||
int result;
|
int result;
|
||||||
struct k_poll_signal sig[2];
|
struct k_poll_signal sig[2];
|
||||||
struct onoff_client cli[2];
|
struct onoff_client cli[2];
|
||||||
const struct onoff_service_transitions transitions =
|
const struct onoff_transitions transitions =
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||||
ONOFF_SERVICE_START_SLEEPS | ONOFF_SERVICE_STOP_SLEEPS);
|
ONOFF_START_SLEEPS
|
||||||
|
| ONOFF_STOP_SLEEPS);
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.async = true;
|
start_state.async = true;
|
||||||
|
@ -1062,7 +1066,7 @@ static void test_blocked_restart(void)
|
||||||
stop_state.async = true;
|
stop_state.async = true;
|
||||||
stop_state.retval = 31;
|
stop_state.retval = 31;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
rc = onoff_manager_init(&srv, &transitions);
|
||||||
zassert_equal(rc, 0,
|
zassert_equal(rc, 0,
|
||||||
"service init");
|
"service init");
|
||||||
|
|
||||||
|
@ -1109,7 +1113,7 @@ static void test_blocked_restart(void)
|
||||||
"isr sync");
|
"isr sync");
|
||||||
|
|
||||||
/* Fail-to-restart is not an error */
|
/* Fail-to-restart is not an error */
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
k_poll_signal_check(&sig[0], &signalled, &result);
|
k_poll_signal_check(&sig[0], &signalled, &result);
|
||||||
|
@ -1127,21 +1131,17 @@ static void test_blocked_restart(void)
|
||||||
|
|
||||||
static void test_cancel_release(void)
|
static void test_cancel_release(void)
|
||||||
{
|
{
|
||||||
|
static const struct onoff_transitions srv_transitions =
|
||||||
|
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
||||||
|
ONOFF_STOP_SLEEPS);
|
||||||
|
struct onoff_manager srv = ONOFF_MANAGER_INITIALIZER(&srv_transitions);
|
||||||
int rc;
|
int rc;
|
||||||
struct onoff_service srv;
|
|
||||||
const struct onoff_service_transitions transitions =
|
|
||||||
ONOFF_SERVICE_TRANSITIONS_INITIALIZER(start, stop, NULL,
|
|
||||||
ONOFF_SERVICE_STOP_SLEEPS);
|
|
||||||
|
|
||||||
clear_transit();
|
clear_transit();
|
||||||
start_state.retval = 16;
|
start_state.retval = 16;
|
||||||
stop_state.async = true;
|
stop_state.async = true;
|
||||||
stop_state.retval = 94;
|
stop_state.retval = 94;
|
||||||
|
|
||||||
rc = onoff_service_init(&srv, &transitions);
|
|
||||||
zassert_equal(rc, 0,
|
|
||||||
"service init");
|
|
||||||
|
|
||||||
init_spinwait(&spinwait_cli);
|
init_spinwait(&spinwait_cli);
|
||||||
rc = onoff_request(&srv, &spinwait_cli);
|
rc = onoff_request(&srv, &spinwait_cli);
|
||||||
zassert_true(rc > 0,
|
zassert_true(rc > 0,
|
||||||
|
@ -1162,13 +1162,13 @@ static void test_cancel_release(void)
|
||||||
rc = onoff_cancel(&srv, &spinwait_cli);
|
rc = onoff_cancel(&srv, &spinwait_cli);
|
||||||
zassert_equal(rc, -EWOULDBLOCK,
|
zassert_equal(rc, -EWOULDBLOCK,
|
||||||
"cancel succeeded");
|
"cancel succeeded");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
|
|
||||||
notify(&stop_state);
|
notify(&stop_state);
|
||||||
zassert_equal(cli_result(&spinwait_cli), stop_state.retval,
|
zassert_equal(cli_result(&spinwait_cli), stop_state.retval,
|
||||||
"release pending");
|
"release pending");
|
||||||
zassert_false(onoff_service_has_error(&srv),
|
zassert_false(onoff_has_error(&srv),
|
||||||
"has error");
|
"has error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue