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-newt.git

commit 6cde3237a522448062936a6815219cf43f82873e
Author: Christopher Collins <ccoll...@apache.org>
AuthorDate: Thu Oct 4 18:53:19 2018 -0700

    sysdown: generate package shutdown function
    
    Allow packages to specify a function to call when the system shuts down.
    The syntax is:
    
        pkg.down:
            <C-function-name>: <stage-number>
    
    e.g.,
    
        pkg.down:
            ble_hs_shutdown: 200
    
    Lower stages execute before greater stages.  If two or more callbacks
    have the same stage, they are sorted alphabetically by C function name.
---
 newt/builder/targetbuild.go | 23 +++++++++++
 newt/pkg/localpackage.go    | 23 ++++++++++-
 newt/sysdown/sysdown.go     | 97 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 1c2f8ba..e4ccc21 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -45,6 +45,7 @@ import (
        "mynewt.apache.org/newt/newt/resolve"
        "mynewt.apache.org/newt/newt/symbol"
        "mynewt.apache.org/newt/newt/syscfg"
+       "mynewt.apache.org/newt/newt/sysdown"
        "mynewt.apache.org/newt/newt/sysinit"
        "mynewt.apache.org/newt/newt/target"
        "mynewt.apache.org/newt/newt/toolchain"
@@ -172,6 +173,10 @@ func (t *TargetBuilder) ensureResolved() error {
                appSeeds = append(appSeeds, t.testPkg)
        }
 
+       // Indicate to the apache-mynewt-core code that this version of newt
+       // supports the sysdown mechanism (generated package shutdown 
functions).
+       t.injectedSettings["NEWT_FEATURE_SYSDOWN"] = "1"
+
        var err error
        t.res, err = resolve.ResolveFull(
                loaderSeeds, appSeeds, t.injectedSettings, t.bspPkg.FlashMap)
@@ -237,6 +242,20 @@ func (t *TargetBuilder) generateSysinit() error {
        return nil
 }
 
+func (t *TargetBuilder) generateSysdown() error {
+       if err := t.ensureResolved(); err != nil {
+               return err
+       }
+
+       srcDir := GeneratedSrcDir(t.target.Name())
+
+       lpkgs := resolve.RpkgSliceToLpkgSlice(t.res.AppSet.Rpkgs)
+       sysdown.EnsureWritten(lpkgs, t.res.Cfg, srcDir,
+               pkg.ShortName(t.target.Package()))
+
+       return nil
+}
+
 func (t *TargetBuilder) generateFlashMap() error {
        return t.bspPkg.FlashMap.EnsureWritten(
                GeneratedSrcDir(t.target.Name()),
@@ -249,6 +268,10 @@ func (t *TargetBuilder) generateCode() error {
                return err
        }
 
+       if err := t.generateSysdown(); err != nil {
+               return err
+       }
+
        if err := t.generateFlashMap(); err != nil {
                return err
        }
diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go
index 6927b38..d5cc9a8 100644
--- a/newt/pkg/localpackage.go
+++ b/newt/pkg/localpackage.go
@@ -361,9 +361,10 @@ func (pkg *LocalPackage) Load() error {
                }
                pkg.init[name] = int(stage)
        }
+
+       // Backwards compatibility: allow old sysinit notation.
        initFnName := pkg.PkgY.GetValString("pkg.init_function", nil)
        initStage := pkg.PkgY.GetValInt("pkg.init_stage", nil)
-
        if initFnName != "" {
                pkg.init[initFnName] = initStage
        }
@@ -391,6 +392,26 @@ func (pkg *LocalPackage) Init() map[string]int {
        return pkg.init
 }
 
+// DownFuncs retrieves the package's shutdown functions.  The returned map has:
+// key=C-function-name, value=numeric-stage.
+func (pkg *LocalPackage) DownFuncs(
+       settings map[string]string) (map[string]int, error) {
+
+       downFuncs := map[string]int{}
+
+       down := pkg.PkgY.GetValStringMapString("pkg.down", settings)
+       for name, stageStr := range down {
+               stage, err := strconv.ParseInt(stageStr, 10, 64)
+               if err != nil {
+                       return nil, util.FmtNewtError("Parsing pkg %s config: 
%s",
+                               pkg.FullName(), err.Error())
+               }
+               downFuncs[name] = int(stage)
+       }
+
+       return downFuncs, nil
+}
+
 func (pkg *LocalPackage) InjectedSettings() map[string]string {
        return pkg.injectedSettings
 }
diff --git a/newt/sysdown/sysdown.go b/newt/sysdown/sysdown.go
new file mode 100644
index 0000000..060130e
--- /dev/null
+++ b/newt/sysdown/sysdown.go
@@ -0,0 +1,97 @@
+/**
+ * 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.
+ */
+
+package sysdown
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+
+       "mynewt.apache.org/newt/newt/newtutil"
+       "mynewt.apache.org/newt/newt/pkg"
+       "mynewt.apache.org/newt/newt/stage"
+       "mynewt.apache.org/newt/newt/syscfg"
+)
+
+// downFuncs collects the sysdown functions corresponding to the provided
+// packages.
+func downFuncs(pkgs []*pkg.LocalPackage,
+       cfg syscfg.Cfg) ([]stage.StageFunc, error) {
+
+       fns := make([]stage.StageFunc, 0, len(pkgs))
+       for _, p := range pkgs {
+               downMap, err := p.DownFuncs(cfg.AllSettingsForLpkg(p))
+               if err != nil {
+                       return nil, err
+               }
+
+               for name, stageNum := range downMap {
+                       fn := stage.StageFunc{
+                               Name:       name,
+                               Stage:      stageNum,
+                               ReturnType: "int",
+                               ArgList:    "int reason",
+                               Pkg:        p,
+                       }
+                       fns = append(fns, fn)
+               }
+       }
+
+       return fns, nil
+}
+
+func sortedDownFuncs(pkgs []*pkg.LocalPackage,
+       cfg syscfg.Cfg) ([]stage.StageFunc, error) {
+
+       fns, err := downFuncs(pkgs, cfg)
+       if err != nil {
+               return nil, err
+       }
+
+       stage.SortStageFuncs(fns, "sysdown")
+       return fns, nil
+}
+
+func write(pkgs []*pkg.LocalPackage, cfg syscfg.Cfg, w io.Writer) error {
+       fmt.Fprintf(w, newtutil.GeneratedPreamble())
+
+       fns, err := sortedDownFuncs(pkgs, cfg)
+       if err != nil {
+               return err
+       }
+
+       stage.WritePrototypes(fns, w)
+
+       fmt.Fprintf(w, "\nint (* const sysdown_cbs[])(int reason) = {\n")
+       stage.WriteArr(fns, w)
+       fmt.Fprintf(w, "};\n")
+
+       return nil
+}
+
+func EnsureWritten(pkgs []*pkg.LocalPackage, cfg syscfg.Cfg, srcDir string,
+       targetName string) error {
+
+       buf := bytes.Buffer{}
+       write(pkgs, cfg, &buf)
+
+       path := fmt.Sprintf("%s/%s-sysdown.c", srcDir, targetName)
+       return stage.EnsureWritten(path, buf.Bytes())
+}

Reply via email to