You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2018/10/23 17:47:59 UTC

[mynewt-newt] 02/02: sysdown: generate package shutdown function

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 <cc...@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())
+}