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