Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pv_error_handling.h Source File

pv_error_handling.h

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //  
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //  
00008 //     http://www.apache.org/licenses/LICENSE-2.0
00009 //  
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 // ----------------------------------------------------------------------------
00016 
00017 #ifndef __PV_ERROR_HANDLING_H__
00018 #define __PV_ERROR_HANDLING_H__
00019 
00020 
00021 #ifdef __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025 #include <assert.h>
00026 #include <stdbool.h>
00027 
00028 #include "pv_log.h"
00029 
00030 
00031 /** The following are macros to enable different error handling in development
00032  *    environment and production environment:
00033  *    On development environment, in oredr to speed up bug fixing we might want
00034  *    to assert or disable CK services. On production we shall not halt since
00035  *    we might get the whole device stuck.
00036  *    The errors are devided into 2 categories:
00037  *    1. recoverable errors - like invalid parameter to API function
00038  *    2. non-recoverable errors - like allocation failures
00039  *    default values for production is to not halt in any case,
00040  *    for development the default is to halt in non-recovrable error only
00041  *    since recoverable error may occure in negative tests
00042  */
00043 #ifdef DEVELOPMENT_ENV
00044 #define HALT_ON_RECOVERABLE_ERRORS()    0
00045 #define HALT_ON_UNRECOVERABLE_ERRORS()  0
00046 #else //if PRODUCTION_ENV
00047 #define HALT_ON_RECOVERABLE_ERRORS()    0
00048 #define HALT_ON_UNRECOVERABLE_ERRORS()  0
00049 #endif
00050 
00051 /**  Set this to 1 to immediately assert when an unrecoverable error is
00052  *    detected in PC environment.
00053  *    While it can be nice to get an immediate assert, often seeing the
00054  *    call trace is more useful - so the default is NOT to assert.
00055  */
00056 #define ASSERT_IN_PC_ENV() 0
00057 
00058 // Currently, this flag is defined in makefile errors.mk
00059 // Set this to 1 in order to completely ignore unrecoverable errors -
00060 // condition won't be checked, nothing would be printed.
00061 // This should only be used in situations where memory is very tight,
00062 // and would render debugging very complicated!
00063 //#define IGNORE_UNRECOVERABLE_ERRORS 0
00064 
00065 
00066 void pv_error_occured(void);
00067 bool pv_error_is_error_occured(void);
00068 
00069 #if  ((HALT_ON_RECOVERABLE_ERRORS()) || (HALT_ON_UNRECOVERABLE_ERRORS()))
00070 #define SA_PV_IS_PREV_ERROR_OCCURED() (pv_error_is_error_occured())
00071 #else
00072 #define SA_PV_IS_PREV_ERROR_OCCURED() (false)
00073 #endif
00074 
00075 
00076 
00077 #define _SA_PV_ERR_ASSERT_UPON_ERROR(cond, return_code, ...) {\
00078     if (cond) { \
00079         SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__);\
00080         assert(!(cond));\
00081         (void)return_code;  /* Mention explicitly to fail compilation if return_code is not compilable. */ \
00082         abort();\
00083     }\
00084 }
00085 
00086 #define _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO(cond, return_code_assignment, goto_label, ...) {\
00087     if (cond) {\
00088         SA_PV_LOG_ERR(__VA_ARGS__);\
00089         assert(!(cond));\
00090         abort();\
00091         return_code_assignment;  /* Mention explicitly to fail compilation if return_code_assignment is not compilable. */ \
00092         goto goto_label;\
00093     }\
00094 }
00095 
00096 #define _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR(cond, return_code, ...) {\
00097     if (cond) {\
00098         SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \
00099         pv_error_occured();\
00100         return return_code;\
00101     }\
00102 }
00103 
00104 #define _SA_PV_RETURN_UPON_ERROR(level, cond, return_code, ...) {\
00105     if (cond) {\
00106         SA_PV_LOG_ ## level ## _FUNC_EXIT(__VA_ARGS__);\
00107         return return_code;\
00108     }\
00109 }
00110 #define _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR(cond, return_code_assignment, goto_label, ...) {\
00111     if (cond) {\
00112         SA_PV_LOG_ERR(__VA_ARGS__);\
00113         pv_error_occured();\
00114         return_code_assignment;\
00115         goto goto_label;\
00116     }\
00117 }
00118 
00119 #define _SA_PV_GOTO_UPON_ERROR(level, cond, return_code_assignment, goto_label, ...) {\
00120     if (cond) {\
00121         SA_PV_LOG_ ## level(__VA_ARGS__); \
00122         return_code_assignment;\
00123         goto goto_label;\
00124     }\
00125 }
00126 
00127 
00128 /**  For non-recoverable errors, if condition fails:
00129  *    log error message
00130  *    if in development and running on PC - assert
00131  *    if in development but not PC - disable further processing with CK and return error code
00132  *    if in case in production (default  behavior), just return error code
00133  */
00134 #if HALT_ON_UNRECOVERABLE_ERRORS()
00135 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
00136 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00137 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00138                 _SA_PV_ERR_ASSERT_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
00139 #else
00140 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00141                 if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
00142 #endif
00143 #else
00144 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00145 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00146                 _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
00147 #else
00148 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00149                 if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
00150 #endif
00151 #endif
00152 #else   // HALT_ON_UNRECOVERABLE_ERRORS  
00153 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00154 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00155             _SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__)
00156 #else
00157 #define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
00158             if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
00159 #endif
00160 #endif // HALT_ON_UNRECOVERABLE_ERRORS
00161 
00162 /**  For non-recoverable errors, if condition fails:
00163  *     log error message
00164  *     if in development and running on PC - assert
00165  *     if in development but not PC - disable further processing with CK and assign error code and goto label
00166  *     if in case in production (default  behavior), just  assign error code and goto label
00167  */
00168 #if HALT_ON_UNRECOVERABLE_ERRORS()
00169 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
00170 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00171 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00172                 _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00173 #else
00174 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00175                 if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
00176                     return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
00177                     goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
00178                 }
00179 #endif
00180 #else
00181 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00182 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00183                 _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00184 #else
00185 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00186                 if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
00187                     return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
00188                     goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
00189                 }
00190 #endif
00191 #endif
00192 #else // HALT_ON_UNRECOVERABLE_ERRORS  
00193 #ifndef IGNORE_UNRECOVERABLE_ERRORS
00194 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00195             _SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00196 #else
00197 #define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00198             if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
00199                 return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
00200                 goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
00201             }
00202 #endif
00203 #endif // HALT_ON_UNRECOVERABLE_ERRORS
00204 
00205 
00206 /** Recoverable errors handling
00207  *    For recoverable errors, if condition fails:
00208  *    log error message
00209  *    if in development and running on PC - assert
00210  *    if in development but not PC - disable further processing with CK and return error code
00211  *    if in case in production (default  behavior), just log and return error code
00212  *    this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log and return error code
00213  */
00214 #if HALT_ON_RECOVERABLE_ERRORS()
00215 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
00216 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00217             _SA_PV_ERR_ASSERT_UPON_ERROR((cond), return_code, ##__VA_ARGS__)
00218 #else
00219 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00220             _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
00221 #endif
00222 #else // HALT_ON_RECOVERABLE_ERRORS
00223 #define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00224         _SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__)
00225 
00226 #define SA_PV_ERR_RECOVERABLE_RETURN(return_code, ...) \
00227         SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \
00228         return return_code;
00229 #endif // HALT_ON_RECOVERABLE_ERRORS
00230 
00231 // if the condition is true:
00232 // Theses macros return with return_code and perform the exit function log (if the log level is appropriate).
00233 
00234 // FIXME: This is partial solution, for critical level, also unrecoverable return should be treated and
00235 // the macros for different  flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.)
00236 #define SA_PV_CRITICAL_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00237     _SA_PV_RETURN_UPON_ERROR(CRITICAL, (cond), (return_code), ##__VA_ARGS__)
00238 //  used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled)
00239 #define SA_PV_WARN_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00240     _SA_PV_RETURN_UPON_ERROR(WARN, (cond), (return_code), ##__VA_ARGS__)
00241 //  used in external APIs
00242 #define SA_PV_INFO_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00243     _SA_PV_RETURN_UPON_ERROR(INFO, (cond), (return_code), ##__VA_ARGS__)
00244 //  used in internal APIs
00245 #define SA_PV_TRACE_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00246     _SA_PV_RETURN_UPON_ERROR(TRACE, (cond), (return_code), ##__VA_ARGS__)
00247 #define SA_PV_DATA_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
00248     _SA_PV_RETURN_UPON_ERROR(DATA, (cond), (return_code), ##__VA_ARGS__)
00249 
00250 /** For recoverable errors, if condition fails:
00251  *    log error message
00252  *    if in development and running on PC - assert
00253  *    if in development but not PC - disable further processing with CK and assign error code and goto label
00254  *    if in case in production (default  behavior), just log, assign error code and goto label
00255  *    this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log, assign error code and goto label
00256  */
00257 #if HALT_ON_RECOVERABLE_ERRORS()
00258 #if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
00259 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00260             _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00261 #else
00262 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00263             _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00264 #endif
00265 #else // HALT_ON_RECOVERABLE_ERRORS
00266 #define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00267         _SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00268 #endif // HALT_ON_RECOVERABLE_ERRORS
00269 
00270 // if the condition is true:
00271 // Theses macros jump to goto_label with return_code and perform log (if the log level is appropriate).
00272 
00273 // FIXME: This is partial solution, for critical level, also unrecoverable goto should be treated and
00274 // the macros for differnet  flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.)
00275 #define SA_PV_CRITICAL_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00276     _SA_PV_GOTO_UPON_ERROR(CRITICAL, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00277 //  used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled)
00278 #define SA_PV_WARN_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00279     _SA_PV_GOTO_UPON_ERROR(WARN, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00280 //  used in external APIs
00281 #define SA_PV_INFO_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00282     _SA_PV_GOTO_UPON_ERROR(INFO, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00283 //  used in internal APIs
00284 #define SA_PV_TRACE_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00285     _SA_PV_GOTO_UPON_ERROR(TRACE, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00286 //  used in functions that are called many times and we don't necessary want to see all its logging even in TRACE mode
00287 #define SA_PV_DATA_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
00288     _SA_PV_GOTO_UPON_ERROR(DATA, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
00289 
00290 #ifdef __cplusplus
00291 }
00292 #endif
00293 
00294 #endif  // __PV_ERROR_HANDLING_H__
00295