This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push: new 54b7b38 Use generated sysdown() function 54b7b38 is described below commit 54b7b38a73811226015a2ac4fa681adafb68f48b Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Thu Oct 4 12:51:55 2018 -0700 Use generated sysdown() function NOTE: This commit requires a newt tool update (dfaede5fbdd0c9d798714abed77b54be2d26bc06). Upon application-triggered restart, execute each package's shutdown subprocedure. This feature is discussed here: https://lists.apache.org/thread.html/ebd53c9b56230184650ea57e5534d5bcfbfc170b97547a1a26f100b5@%3Cdev.mynewt.apache.org%3E --- kernel/os/include/os/mynewt.h | 1 + kernel/os/include/os/os.h | 11 ++ kernel/os/pkg.yml | 3 +- kernel/os/src/os.c | 18 ++++ mgmt/newtmgr/nmgr_os/src/newtmgr_os.c | 8 +- sys/shell/src/shell_os.c | 3 +- sys/sysdown/include/sysdown/sysdown.h | 118 ++++++++++++++++++++ {kernel/os => sys/sysdown}/pkg.yml | 29 +---- sys/sysdown/src/sysdown.c | 162 ++++++++++++++++++++++++++++ kernel/os/pkg.yml => sys/sysdown/syscfg.yml | 46 ++++---- 10 files changed, 336 insertions(+), 63 deletions(-) diff --git a/kernel/os/include/os/mynewt.h b/kernel/os/include/os/mynewt.h index ca544ee..910e642 100644 --- a/kernel/os/include/os/mynewt.h +++ b/kernel/os/include/os/mynewt.h @@ -21,6 +21,7 @@ #define H_OS_MYNEWT_ #include "syscfg/syscfg.h" +#include "sysdown/sysdown.h" #include "sysinit/sysinit.h" #include "sysflash/sysflash.h" #include "os/os.h" diff --git a/kernel/os/include/os/os.h b/kernel/os/include/os/os.h index 40cbf54..5353832 100644 --- a/kernel/os/include/os/os.h +++ b/kernel/os/include/os/os.h @@ -107,6 +107,17 @@ void os_init(int (*fn)(int argc, char **argv)); */ void os_start(void); +/** + * Reboots the system. + */ +void os_reboot(int reason); + +/** + * Performs a system reset. This is typically done at the end of a reboot + * procedure. + */ +void os_system_reset(void); + #include "os/endian.h" #include "os/os_callout.h" #include "os/os_cfg.h" diff --git a/kernel/os/pkg.yml b/kernel/os/pkg.yml index b1dffa5..dd0ea64 100644 --- a/kernel/os/pkg.yml +++ b/kernel/os/pkg.yml @@ -24,8 +24,9 @@ pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: pkg.deps: - - "@apache-mynewt-core/sys/sysinit" - "@apache-mynewt-core/sys/sys" + - "@apache-mynewt-core/sys/sysdown" + - "@apache-mynewt-core/sys/sysinit" - "@apache-mynewt-core/util/mem" pkg.req_apis: diff --git a/kernel/os/src/os.c b/kernel/os/src/os.c index 3a3c8e9..3bad696 100644 --- a/kernel/os/src/os.c +++ b/kernel/os/src/os.c @@ -24,6 +24,7 @@ #include "hal/hal_os_tick.h" #include "hal/hal_bsp.h" +#include "hal/hal_system.h" #include "hal/hal_watchdog.h" #if MYNEWT_VAL(RTT) @@ -258,6 +259,23 @@ os_start(void) } void +os_reboot(int reason) +{ + sysdown(reason); +} + +void +os_system_reset(void) +{ + /* Tickle watchdog just before re-entering bootloader. Depending on what + * the system has been doing lately, the watchdog timer might be close to + * firing. + */ + hal_watchdog_tickle(); + hal_system_reset(); +} + +void os_pkg_init(void) { os_error_t err; diff --git a/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c b/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c index c83ee24..6c04186 100644 --- a/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c +++ b/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c @@ -307,13 +307,7 @@ nmgr_datetime_set(struct mgmt_cbuf *cb) static void nmgr_reset_tmo(struct os_event *ev) { - /* - * Tickle watchdog just before re-entering bootloader. - * Depending on what system has been doing lately, watchdog - * timer might be close to firing. - */ - hal_watchdog_tickle(); - hal_system_reset(); + os_reboot(HAL_RESET_REQUESTED); } static int diff --git a/sys/shell/src/shell_os.c b/sys/shell/src/shell_os.c index eea6548..08a5fde 100644 --- a/sys/shell/src/shell_os.c +++ b/sys/shell/src/shell_os.c @@ -170,7 +170,8 @@ shell_os_reset_cmd(int argc, char **argv) } #endif os_time_delay(OS_TICKS_PER_SEC / 10); - hal_system_reset(); + os_reboot(HAL_RESET_REQUESTED); + return 0; } #if MYNEWT_VAL(SHELL_CMD_HELP) diff --git a/sys/sysdown/include/sysdown/sysdown.h b/sys/sysdown/include/sysdown/sysdown.h new file mode 100644 index 0000000..ebb7d6c --- /dev/null +++ b/sys/sysdown/include/sysdown/sysdown.h @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_SYSDOWN_ +#define H_SYSDOWN_ + +#include <inttypes.h> +#include <assert.h> +#include <stdbool.h> +#include "syscfg/syscfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYSDOWN_COMPLETE 0 +#define SYSDOWN_IN_PROGRESS 1 + +/** + * Whether the system is currently shutting down + */ +extern bool sysdown_active; + +typedef int sysdown_fn(int reason); +typedef void sysdown_panic_fn(const char *file, int line, const char *func, + const char *expr, const char *msg); +typedef void sysdown_complete_fn(int status, void *arg); + +extern sysdown_fn * const sysdown_cbs[]; +extern sysdown_panic_fn *sysdown_panic_cb; + +void sysdown_panic_set(sysdown_panic_fn *panic_fn); + +#if MYNEWT_VAL(SYSDOWN_PANIC_MESSAGE) + +#if MYNEWT_VAL(SYSDOWN_PANIC_FILE_LINE) +#define SYSDOWN_PANIC_MSG(msg) sysdown_panic_cb(__FILE__, __LINE__, 0, 0, msg) +#else +#define SYSDOWN_PANIC_MSG(msg) sysdown_panic_cb(0, 0, 0, 0, msg) +#endif + +#else + +#if MYNEWT_VAL(SYSDOWN_PANIC_FILE_LINE) +#define SYSDOWN_PANIC_MSG(msg) sysdown_panic_cb(__FILE__, __LINE__, 0, 0, 0) +#else +#define SYSDOWN_PANIC_MSG(msg) sysdown_panic_cb(0, 0, 0, 0, 0) +#endif + +#endif + +#define SYSDOWN_PANIC() SYSDOWN_PANIC_MSG(NULL) + +#define SYSDOWN_ASSERT_MSG(rc, msg) do \ +{ \ + if (!(rc)) { \ + SYSDOWN_PANIC_MSG(msg); \ + } \ +} while (0) + +#define SYSDOWN_ASSERT(rc) SYSDOWN_ASSERT_MSG(rc, NULL) + +/** + * Asserts that system shutdown is in progress. This macro is used to ensure + * packages don't get shut down a second time after system shutdown has + * completed. + */ +#if MYNEWT_VAL(SYSDOWN_CONSTRAIN_DOWN) +#define SYSDOWN_ASSERT_ACTIVE() assert(sysdown_active) +#else +#define SYSDOWN_ASSERT_ACTIVE() +#endif + +/** + * @brief Performs a controlled shutdown and reset of the system. + * + * This function executes each package's shutdown sequence, then triggers a + * reboot. + * + * @param reason The reason for the shutdown. One of the + * HAL_RESET_[...] codes or an + * implementation-defined value. + * + * @return + */ +int sysdown(int reason); + +/** + * @brief Signals completion of an in-progress sysdown subprocedure. + * + * If a sysdown subprocedure needs to perform additional work after its + * callback finishes, it returns SYSDOWN_IN_PROGRESS. Later, when the + * subprocedure completes, it signals its completion asynchronously with a call + * to this function. + */ +void sysdown_release(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/os/pkg.yml b/sys/sysdown/pkg.yml similarity index 62% copy from kernel/os/pkg.yml copy to sys/sysdown/pkg.yml index b1dffa5..461da41 100644 --- a/kernel/os/pkg.yml +++ b/sys/sysdown/pkg.yml @@ -17,34 +17,11 @@ # under the License. # -pkg.name: kernel/os -pkg.description: Mynewt operating system core. +pkg.name: sys/sysdown +pkg.description: Package for kicking off a controlled system shutdown. pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: pkg.deps: - - "@apache-mynewt-core/sys/sysinit" - - "@apache-mynewt-core/sys/sys" - - "@apache-mynewt-core/util/mem" - -pkg.req_apis: - - console - -pkg.deps.OS_CLI: - - "@apache-mynewt-core/sys/shell" - -pkg.deps.OS_COREDUMP: - - "@apache-mynewt-core/sys/coredump" - -pkg.deps.BSP_SIMULATED: - - "@apache-mynewt-core/kernel/sim" - -pkg.deps.OS_SYSVIEW: - - "@apache-mynewt-core/sys/sysview" - -pkg.deps.OS_CRASH_LOG: - - "@apache-mynewt-core/sys/reboot" - -pkg.init: - os_pkg_init: 0 + - "@apache-mynewt-core/kernel/os" diff --git a/sys/sysdown/src/sysdown.c b/sys/sysdown/src/sysdown.c new file mode 100644 index 0000000..682eadb --- /dev/null +++ b/sys/sysdown/src/sysdown.c @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "os/mynewt.h" + +/** + * The NEWT_FEATURE_SYSDOWN setting is injected by new-enough versions of the + * newt tool. + */ +#if !MYNEWT_VAL(NEWT_FEATURE_SYSDOWN) + +int +sysdown(int reason) +{ + os_system_reset(); + return 0; +} + +#else + +#include <assert.h> +#include <stdio.h> +#include <stddef.h> +#include <limits.h> +#include "hal/hal_system.h" +#include "hal/hal_watchdog.h" + +#define SYSDOWN_TIMEOUT_TICKS \ + (MYNEWT_VAL(SYSDOWN_TIMEOUT_MS) * OS_TICKS_PER_SEC / 1000) + +_Static_assert(SYSDOWN_TIMEOUT_TICKS >= 0 && SYSDOWN_TIMEOUT_TICKS < INT32_MAX, + "SYSDOWN_TIMEOUT_MS value not in valid range"); + +static volatile int sysdown_num_in_progress; +bool sysdown_active; +static struct os_callout sysdown_timer; + +static void +sysdown_dflt_panic_cb(const char *file, int line, const char *func, + const char *expr, const char *msg) +{ +#if MYNEWT_VAL(SYSDOWN_PANIC_MESSAGE) + if (msg != NULL) { + fprintf(stderr, "sysdown failure: %s\n", msg); + } +#endif + + __assert_func(file, line, func, expr); +} + +sysdown_panic_fn *sysdown_panic_cb = sysdown_dflt_panic_cb; + +/** + * Sets the sysdown panic function; i.e., the function which executes when + * shutdown fails. By default, a panic triggers a failed assertion. + */ +void +sysdown_panic_set(sysdown_panic_fn *panic_cb) +{ + sysdown_panic_cb = panic_cb; +} + +static void +sysdown_complete(void) +{ + os_callout_stop(&sysdown_timer); + os_system_reset(); +} + +void +sysdown_release(void) +{ + os_sr_t sr; + int count; + + OS_ENTER_CRITICAL(sr); + count = --sysdown_num_in_progress; + OS_EXIT_CRITICAL(sr); + + if (count <= 0) { + sysdown_complete(); + } +} + +static void +sysdown_timer_exp(struct os_event *unused) +{ + assert(0); +} + +int +sysdown(int reason) +{ + os_sr_t sr; + int rc; + int i; + + /* Only allow one shutdown operation. */ + OS_ENTER_CRITICAL(sr); + if (sysdown_active) { + rc = SYS_EALREADY; + } else { + sysdown_active = true; + rc = 0; + } + OS_EXIT_CRITICAL(sr); + + if (rc != 0) { + return rc; + } + + os_callout_init(&sysdown_timer, os_eventq_dflt_get(), sysdown_timer_exp, + NULL); + rc = os_callout_reset(&sysdown_timer, SYSDOWN_TIMEOUT_TICKS); + assert(rc == 0); + + /* Call each configured sysdown callback. */ + for (i = 0; sysdown_cbs[i] != NULL; i++) { + rc = sysdown_cbs[i](reason); + switch (rc) { + case SYSDOWN_COMPLETE: + break; + + case SYSDOWN_IN_PROGRESS: + OS_ENTER_CRITICAL(sr); + sysdown_num_in_progress++; + OS_EXIT_CRITICAL(sr); + break; + + default: + break; + } + } + + /* If all subprocedures are complete, signal completion of sysdown. + * Otherwise, wait for in-progress subprocedures to signal completion + * asynchronously. + */ + if (sysdown_num_in_progress == 0) { + sysdown_complete(); + } + + return 0; +} + +#endif diff --git a/kernel/os/pkg.yml b/sys/sysdown/syscfg.yml similarity index 52% copy from kernel/os/pkg.yml copy to sys/sysdown/syscfg.yml index b1dffa5..a5697a7 100644 --- a/kernel/os/pkg.yml +++ b/sys/sysdown/syscfg.yml @@ -1,4 +1,3 @@ -# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -17,34 +16,25 @@ # under the License. # -pkg.name: kernel/os -pkg.description: Mynewt operating system core. -pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - -pkg.deps: - - "@apache-mynewt-core/sys/sysinit" - - "@apache-mynewt-core/sys/sys" - - "@apache-mynewt-core/util/mem" - -pkg.req_apis: - - console - -pkg.deps.OS_CLI: - - "@apache-mynewt-core/sys/shell" - -pkg.deps.OS_COREDUMP: - - "@apache-mynewt-core/sys/coredump" +# Package: sys/sysdown -pkg.deps.BSP_SIMULATED: - - "@apache-mynewt-core/kernel/sim" +syscfg.defs: + SYSDOWN_CONSTRAIN_DOWN: + description: Only allow packages to be shutdown by sysdown. + value: 1 -pkg.deps.OS_SYSVIEW: - - "@apache-mynewt-core/sys/sysview" + SYSDOWN_PANIC_FILE_LINE: + description: Include filename and line number in sysdown panic. + value: 0 -pkg.deps.OS_CRASH_LOG: - - "@apache-mynewt-core/sys/reboot" + SYSDOWN_PANIC_MESSAGE: + description: Include descriptive message in sysdown panic. + value: 0 -pkg.init: - os_pkg_init: 0 + SYSDOWN_TIMEOUT_MS: + description: > + Total duration, in milliseconds, before the shutdown procedure + times out. On timeout, the system triggers a failed assertion. + NOTE: This timeout applies to the full shutdown procedure, not to a + single subprocedure. + value: 10000