Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #24329 > unrolled thread

Common name for a "Task Loop"

Started byTim Wescott <seemywebsite@myfooter.really>
First post2016-06-24 13:37 -0500
Last post2016-07-14 20:44 +0000
Articles 20 on this page of 196 — 27 participants

Back to article view | Back to comp.arch.embedded


Contents

  Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-24 13:37 -0500
    Re: Common name for a "Task Loop" Lanarcam <lanarcam1@yahoo.fr> - 2016-06-24 21:04 +0200
      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-24 15:21 -0500
    Re: Common name for a "Task Loop" Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2016-06-24 22:46 +0300
    Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-24 14:51 -0500
      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-24 15:10 -0500
    Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-06-24 20:11 +0000
      Re: Common name for a "Task Loop" gtwrek@sonic.net (Mark Curry) - 2016-06-24 20:31 +0000
    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-24 13:21 -0700
      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-24 18:31 -0500
        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-24 17:03 -0700
          Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-25 10:52 +0300
            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 01:07 -0700
              Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-25 14:00 +0300
                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 08:27 -0700
                  Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-25 15:50 -0500
                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 14:45 -0700
                      Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-25 17:28 -0500
                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 00:40 -0700
                      Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-26 12:41 +0300
              Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-25 15:46 -0500
                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 14:42 -0700
          Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-25 15:43 -0500
            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 14:36 -0700
              Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-25 17:25 -0500
                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 00:14 -0700
    Re: Common name for a "Task Loop" Paul Rubin <no.email@nospam.invalid> - 2016-06-24 14:00 -0700
      Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-25 15:27 +0000
        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 09:41 -0700
          Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-25 17:59 +0000
            Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-25 16:24 -0500
              Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-26 23:36 +0000
                Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-26 19:00 -0500
                Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-27 05:53 +0300
                  Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-27 09:43 -0500
                    Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-28 02:39 +0000
            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 15:08 -0700
              Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-26 23:54 +0000
                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 18:12 -0700
                  Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-06-28 02:54 +0000
                    Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-28 06:20 +0300
                      Re: Common name for a "Task Loop" raimond.dragomir@gmail.com - 2016-06-27 22:57 -0700
                      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-28 09:40 -0500
                        Re: Common name for a "Task Loop" Mel Wilson <mwilson@the-wire.com> - 2016-06-28 15:38 +0000
                          Re: Common name for a "Task Loop" raimond.dragomir@gmail.com - 2016-06-28 08:57 -0700
                        Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-06-28 16:49 +0000
                          Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-28 15:35 -0500
                          Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 13:54 -0700
                            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 14:04 -0700
                              Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-06-28 21:09 +0000
                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 15:14 -0700
                                  Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-06-28 22:30 +0000
                                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 16:06 -0700
                                      Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 16:18 -0700
                                    Re: Common name for a "Task Loop" Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-06-29 01:32 +0200
                        Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-29 01:00 +0300
                          Re: Common name for a "Task Loop" Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-06-29 00:20 +0200
                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-29 02:07 +0300
                          Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-06-28 22:21 +0000
                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-29 02:20 +0300
                          Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-06-28 17:39 -0500
                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-29 02:29 +0300
                              Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-29 09:50 -0500
                          Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 15:43 -0700
                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-29 02:40 +0300
                              Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 16:56 -0700
                            Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-29 08:04 +0300
                              Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 23:22 -0700
                                Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-30 09:02 +0300
                                  Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-30 02:33 -0700
                                    Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-02 14:27 +0300
                                      Re: Common name for a "Task Loop" Wouter van Ooijen <wouter@voti.nl> - 2016-07-02 14:50 +0200
                                        Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-02 20:18 +0300
                                      Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-02 07:36 -0700
                                        Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-02 21:44 +0300
                                          Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-02 14:36 -0700
                                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-03 06:23 +0300
                                              Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-03 00:43 -0700
                          Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-29 11:36 -0500
                            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-29 09:55 -0700
                              Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-29 12:53 -0500
                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-29 11:29 -0700
                                  Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-29 13:41 -0500
                                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-29 11:49 -0700
                                Re: Common name for a "Task Loop" Richard Damon <Richard@Damon-Family.org> - 2016-07-02 20:48 -0700
                                  Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-03 03:07 -0500
                                    Re: Common name for a "Task Loop" Richard Damon <Richard@Damon-Family.org> - 2016-07-03 08:06 -0700
                                      Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-03 12:39 -0500
                                        Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-03 21:44 +0300
                                        Re: Common name for a "Task Loop" Richard Damon <Richard@Damon-Family.org> - 2016-07-03 16:39 -0700
                                          Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-03 23:57 -0500
                                            Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-04 14:39 -0500
                                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-05 06:04 +0300
                                              Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-07-05 11:58 -0500
                                                Re: Common name for a "Task Loop" Reinhardt Behm <rbehm@hushmail.com> - 2016-07-06 10:39 +0800
                                                  Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-07-06 10:11 -0500
                                              Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-05 21:57 +0300
                                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-05 12:20 -0700
                                            Re: Common name for a "Task Loop" Richard Damon <Richard@Damon-Family.org> - 2016-07-04 10:08 -0700
                                          Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-05 11:59 -0700
                                            Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-05 22:51 +0300
                                              Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-05 13:16 -0700
                                                Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-06 11:31 +0300
                                                  Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-06 03:06 -0700
                                                    Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-06 21:37 +0300
                                                      Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-07 00:50 -0400
                                                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-06 23:16 -0700
                                                          Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-07 21:36 +0300
                                                            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-07 12:06 -0700
                                                              Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-07 23:09 +0300
                                                                Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-07-08 11:06 -0500
                                                                  Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-08 12:50 -0500
                                                                    Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-08 23:33 +0300
                                                                      Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-08 16:40 -0500
                                                                    Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-08 23:47 +0300
                                                                      Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-08 16:48 -0500
                                                                        Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-09 21:37 +0300
                                                                          Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-09 14:26 -0500
                                                                            Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-10 00:48 +0300
                                                                              Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-10 03:29 -0500
                                                                                Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-11 06:51 +0300
                                                                                  Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-11 16:11 +0300
                                                                                    Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-11 12:04 -0500
                                                                                    Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-12 11:31 +0300
                                                                                      Re: Common name for a "Task Loop" mac <acolvin@efunct.com> - 2016-07-12 15:08 +0000
                                                                                        Re: Common name for a "Task Loop" Robert Wessel <robertwessel2@yahoo.com> - 2016-07-12 21:24 -0500
                                                                                      Memory scrubbing [Was Re: Common name for a "Task Loop"] Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-12 21:11 +0300
                                                                                    Re: Common name for a "Task Loop" Robert Wessel <robertwessel2@yahoo.com> - 2016-07-12 21:11 -0500
                                                                  Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-08 23:35 +0300
                                                                    Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-08 23:54 +0300
                                                                      Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-09 09:34 +0300
                                                                        Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-09 10:28 +0300
                                                                        Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-09 14:39 -0500
                                                                    Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-07-08 16:56 -0500
                                                                      Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-09 15:46 +0300
                                                                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-10 02:41 -0700
                                                                          Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-10 17:55 +0300
                                                                            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-16 16:34 -0700
                                                                            Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-17 09:56 +0300
                                                                              Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-18 00:08 -0400
                                                                                Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-18 21:16 +0300
                                                                                  Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-18 23:54 -0400
                                                                                    Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-19 10:02 +0300
                                                                                  Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-25 02:56 -0700
                                                                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-25 02:40 -0700
                                                                                  Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-25 17:32 -0400
                                                                                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-25 16:56 -0700
                                                                                      Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-26 06:27 -0400
                                                                                        Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-26 15:59 +0300
                                                                                          Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-26 06:55 -0700
                                                                                          Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-26 17:14 +0300
                                                                                          Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-26 12:50 -0400
                                                                                            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-26 22:07 -0700
                                                                                              Re: Common name for a "Task Loop" George Neuner <gneuner2@comcast.net> - 2016-07-27 14:22 -0400
                                                                                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-08-03 04:58 -0700
                                                                                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-26 06:38 -0700
                                                                    Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-07-09 01:28 +0300
                                                                      Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-09 09:25 +0300
                                                                        Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-09 21:47 +0300
                                                                      Re: Common name for a "Task Loop" Mike Perkins <spam@spam.com> - 2016-07-09 11:18 +0100
                                                                      Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-09 21:41 +0300
                                                                    Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-07-09 20:52 -0500
                                                                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-07-10 02:01 -0700
                                                                  Re: Common name for a "Task Loop" Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-10 17:34 +0300
                                                                    Re: Common name for a "Task Loop" [long] Don Y <blockedofcourse@foo.invalid> - 2016-07-17 01:17 -0700
                                                            Re: Common name for a "Task Loop" Tim Wescott <seemywebsite@myfooter.really> - 2016-07-07 16:02 -0500
                            Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-30 04:14 +0300
                              Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-30 17:07 -0500
                                Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-07-01 02:28 +0300
                      Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 12:02 -0700
                        Re: Common name for a "Task Loop" Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2016-06-28 23:19 +0200
                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-28 11:51 -0700
                      Re: Common name for a "Task Loop" Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> - 2016-07-01 06:54 +0000
          Re: Common name for a "Task Loop" Dimiter_Popoff <dp@tgi-sci.com> - 2016-06-25 21:08 +0300
            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-25 15:24 -0700
          Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-25 21:52 +0300
            Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 01:04 -0700
              Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-26 13:46 +0300
                Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 05:11 -0700
                  Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-26 15:35 +0300
                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 06:57 -0700
                  Re: Common name for a "Task Loop" Reinhardt Behm <rbehm@hushmail.com> - 2016-06-26 21:18 +0800
                    Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 07:07 -0700
                      Re: Common name for a "Task Loop" upsidedown@downunder.com - 2016-06-26 17:35 +0300
                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 07:50 -0700
                      Re: Common name for a "Task Loop" Reinhardt Behm <rbehm@hushmail.com> - 2016-06-26 22:37 +0800
                        Re: Common name for a "Task Loop" Don Y <blockedofcourse@foo.invalid> - 2016-06-26 08:18 -0700
    Re: Common name for a "Task Loop" Dave Nadler <drn@nadler.com> - 2016-06-25 22:00 -0700
      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-26 11:01 -0500
      Re: Common name for a "Task Loop" Les Cargill <lcargill99@comcast.com> - 2016-06-26 19:28 -0500
    Re: Common name for a "Task Loop" FreeRTOS info <noemail@given.com> - 2016-06-27 08:33 +0100
      Re: Common name for a "Task Loop" Tim Wescott <tim@seemywebsite.com> - 2016-06-28 09:48 -0500
        Re: Common name for a "Task Loop" raimond.dragomir@gmail.com - 2016-06-28 08:25 -0700
    Re: Common name for a "Task Loop" Chris <xxx.syseng.yyy@gfsys.co.uk> - 2016-07-03 17:39 +0000
    Re: Common name for a "Task Loop" WangoTango <Asgard24@mindspring.com> - 2016-07-14 16:27 -0400
      Re: Common name for a "Task Loop" Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2016-07-14 20:44 +0000

Page 9 of 10 — ← Prev page 1 … 7 8 [9] 10  Next page →


#24588

FromNiklas Holsti <niklas.holsti@tidorum.invalid>
Date2016-07-09 21:41 +0300
Message-ID<ducur2FlhfnU1@mid.individual.net>
In reply to#24581
On 16-07-09 01:28 , upsidedown@downunder.com wrote:
> On Fri, 8 Jul 2016 23:35:22 +0300, Niklas Holsti
> <niklas.holsti@tidorum.invalid> wrote:
    [snip]
>> One example of interactions I find difficult is a shared I/O channel or
>> bus that must be used by various tasks, for various purposes, with most
>> transmissions being sporadic and such that the sending task must wait
>> for and check a response transmission. I believe that there are analysis
>> methods which can find bounds on the response times for these tasks,
>> including queueing delays and communication latencies, but I haven't
>> studied or tried them yet. I may have to do so in my current project,
>> however, because the system has three inter-communicating computers,
>> with each computer connected by one SpaceWire link to a central router.
>
> I would never even dream of letting multiple tasks directly accessing
> a serial line.
>
> Just put a high priority task on every serial line and let it do the
> arbitration between the application tasks. You can put much more
> intelligence than into the ISR.

I was not speaking of an *implementation* difficulty, but of the 
difficulty of *analysing* the resulting client-task timing and response 
times.

Of course the implementation uses one or more transmit queues, a 
dedicated channel-server task, interrupt handling, and possibly a 
separate channel-receiver task (for full-duplex channels).

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

[toc] | [prev] | [next] | [standalone]


#24593

FromTim Wescott <tim@seemywebsite.com>
Date2016-07-09 20:52 -0500
Message-ID<dJOdnZ7Cf7bGNxzKnZ2dnUU7-dWdnZ2d@giganews.com>
In reply to#24575
On Fri, 08 Jul 2016 23:35:22 +0300, Niklas Holsti wrote:

> On 16-07-08 19:06 , Tim Wescott wrote:
>> On Thu, 07 Jul 2016 23:09:08 +0300, Niklas Holsti wrote:
>>> Don Y wrote:
>>> [snips]
>>>> Or, is it just "some suggestive feeling"
>>>> that led to the small integers chosen?
>>>
>>> No. From the requirements, I derive a set of tasks and deadlines, and
>>> then assign priorities in deadline-monotonic order. Then I analyse or
>>> measure WCETs and crank the response-time algorithm to check
>>> schedulability. The main problem is that the task interactions are
>>> often more complex than assumed by the simpler schedulability analysis
>>> methods. Fortunately, in my projects it is usually possible to
>>> separate hard-real-time tasks from soft-real-time tasks, and the
>>> interactions of the hard-real-time tasks tend to be rather simple.
>>
>> I have never had a problem doing this separation myself, although I've
>> inherited code from other people that fails at this, and rather badly.
>> The most egregious example of this was code that put the most important
>> two jobs into one superloop inside of one task -- and did so in such a
>> way that bollixed up the whole system if incoming commands exceeded a
>> rather moderate rate.
>>
>> I'm not entirely sure, but I think there's a possibility that if your
>> code _does_ have such an interaction between tasks, then it means that
>> there's something fundamentally wrong with your software design, or
>> possibly your system design as a whole.
> 
> I agree that some troublesome task-to-task interactions are design flaws
> and can be eliminated by design changes, sometimes by splitting some
> task into one hard-real-time task and another less urgent task. But I
> have not always succeeded at that.
> 
> One example of interactions I find difficult is a shared I/O channel or
> bus that must be used by various tasks, for various purposes, with most
> transmissions being sporadic and such that the sending task must wait
> for and check a response transmission. I believe that there are analysis
> methods which can find bounds on the response times for these tasks,
> including queueing delays and communication latencies, but I haven't
> studied or tried them yet. I may have to do so in my current project,
> however, because the system has three inter-communicating computers,
> with each computer connected by one SpaceWire link to a central router.

In a sense this becomes a problem in system design, because any real-time 
constraints on the messages has to affect the signaling protocol.  

One of the Really Nice things about the CAN bus, from my perspective as 
both a writer of embedded software and a designer of closed-loop control 
systems, is that the messages are both prioritized and have a well-
defined maximum length.  This means that if you design your prioritization 
scheme correctly, low-latency traffic can coexist with far slower traffic 
-- you just need a higher-layer protocol that can break large messages up 
into many shorter ones on the transmit end, and reassemble them at the 
receive end.

(Priority plus messages of indeterminate length won't get you there -- 
imagine starting a long, low-priority message just before some short, low-
latency message needs to get through.  Unless the protocol encompasses 
terminating the long message, your system is screwed.)

-- 
Tim Wescott
Control systems, embedded software and circuit design
I'm looking for work!  See my website if you're interested
http://www.wescottdesign.com

[toc] | [prev] | [next] | [standalone]


#24595

FromDon Y <blockedofcourse@foo.invalid>
Date2016-07-10 02:01 -0700
Message-ID<nlt2rs$s76$1@dont-email.me>
In reply to#24569
On 7/7/2016 1:09 PM, Niklas Holsti wrote:
> Don Y wrote:
>>>> Exactly.  "Priority" (in the sense of "set_task_priority()") is just
>>>> an expedient to make coding a scheduler easy.  It tells you *nothing*
>>>> about the task's "importance", "timeliness constraints", etc.
>
> Niklas Holsti wrote:
>>> That is not so, if you follow a systematic and proven
>>> priority-assignment rule.
>>> For example, if you use deadline-monotonic priorities then the order
>>> of task
>>> priorities is equivalent to the order of task deadlines (expressed as the
>>> maximum duration between task activation and completion). So then the
>>> task
>>> priorities certainly tell you a lot about the (relative) timeliness
>>> constraints.
>>>
>>> If you just assign priorities based on some subjective "task importance"
>>> feeling, your statement is valid.
>
> Don Y wrote:
>> Then, EVERY product that employs a priority-based scheduler should have a
>> FORMAL document in part of its deliverables that clearly states these
>> priorities and the method by which they were derived (as you later call
>> them "the basis for one important set of the mathematical methods for
>> verifying real-time performance: schedulability analysis").  So, the
>> next bloke to look at the code knows exactly why they were chosen and
>> which assumptions he/she must *continue* to operate under for those
>> priority assignments to remain valid.
>
> Ideally yes, just as every mechanical engineering project should document its
> design assumptions, stress and strength calculations, etc., and every SW
> project should deliver full design documentation, complete user manuals,
> maintenance manuals, etc.
>
> But seriously, documentation requirements are a different dimension from the
> choice of design and implementation methods. Using a systematic design method
> does not oblige you to document the design, although it makes it much easier to
> document it.

How can you say that?  Do you expect the next soul to read your mind
regarding how and why you made specific choices?  Do you expect them
to retrace your design steps to ensure they understand the assumptions
you've ENCODED in your choice of priorities?

Or, are they free to change your priorities WITH NO EFFECT ON THE
RESULTING IMPLEMENTATION?

If you choose a particular value/rating for a component in a
circuit, you either explicitly document WHY you made that choice
*or* assume it is readily apparent to someone looking at the
schematic diagram: "OK, conditions in which this component
operates are such that this performance criteria is adequately
derated for its reliable use, here"

Are the reasons for your SOFTWARE design choices somehow less
important?

E.g., I am particularly fond of pointers and recursive solutions.
To me, they make the algorithms simpler and more robust.

But, I am careful to document how and why each of these mechanisms
are used and "prove" that they *can't* run amok in my description
of the algorithms, etc.  And, the assumptions that dictate how
future uses/adaptations must operate.

>> Ask yourself how many of those documents you've seen?  Authored?
>
> Several, for both questions. All the day-job projects I work on have such, and
> I am usually the author.

I suspect you are in the minority as (IME) most folks using priority
based schedulers just "pick numbers" and, later, "tweek them" to make
their design work properly.  Usually, with little formal knowledge of
the limitations of the algorithms or the problems that can manifest
(nor the potential solutions *or* the problems with the solutions!)

Would you care to share any of those rationales?  I'm hosting a course
that presents various OS design techniques, scheduling algorithms,
hazzards, etc. and examples of how to (and NOT to) exploit each later
this Fall.  "Fabricating" artificial examples always *feels* like an
artifice; presenting REAL examples allows folks to see ACTUAL tradeoffs.

"This is *why* this approach was chosen over this OTHER approach..."

>> Or, is it just "some suggestive feeling"
>> that led to the small integers chosen?
>
> No. From the requirements, I derive a set of tasks and deadlines, and then
> assign priorities in deadline-monotonic order. Then I analyse or measure WCETs
> and crank the response-time algorithm to check schedulability. The main problem
> is that the task interactions are often more complex than assumed by the
> simpler schedulability analysis methods. Fortunately, in my projects it is
> usually possible to separate hard-real-time tasks from soft-real-time tasks,
> and the interactions of the hard-real-time tasks tend to be rather simple.

And, I suspect, your tasks are largely *periodic*?  And/or orthogonal to
each other?

I have had exactly one project in 40 years of RT design that fit that
mold -- a process that ran at 200Hz (5ms cycle time) with "hard"
deadlines (in the sense that a deadline missed resulted in a failure
of that *cycle* of the process -- a "defective product" to be discarded).
Note that missed hard deadlines didn't indicate a failed *implementation*!

By and large, my projects have consisted of aperiodic, cooperating
tasks driven by "semi-random processes"; processes that can't be easily
quantified nor constrained!  And, running on under-provisioned hardware.

E.g., the example up-thread has a bunch of user I/O's:
- barcode reader
- two serial ports
- keypad
- sensor array
- display
- audio annunciator (sound synthesizer)

There is nothing I can do to prevent a user from scanning a barcode
label at *any* time in the normal operation of the system.  I.e.,
"bars" (not "labels") can arrive for processing at any time.  That's
part of the *appeal* of the system -- the USER drives it instead
of *it* driving the user!

There is nothing I can do to prevent the external hosts from interacting
with the device (independantly of each other as well as the user's
activities).  I can't even *guarantee* that they will honor handshaking
and/or pacing controls.  Yet, I can't erroneously behave in the presence
of THEIR bad behavior!

I can't prevent the user from pressing keys at any time.  Indeed, he
may need to "tell me" something that he deems important.

The sensor array lets me track where blood samples and reagents are
being placed by the user -- sort of a keyboard for "droplets".
I can't limit when or where the user pipettes those samples (yet
I must be able to reliably *see* them else I can't vouch for
their integrity and identity).  I can't even guarantee that the
user won't unplug the sensor array, unplug a comm cable, turn off
power, etc. whenever he chooses.

The display must be refreshed else the user loses that information
channel.  Ditto for audio.  (amusingly, this aspect of the user
interface is the LEAST important!)

I can't control when the power might fail.  Though I can probably place
an upper limit on how OFTEN it can fail!  Or, when the battery backup
will give up the ghost, unceremoniously (the user may have disconnected
the battery *or* not given the device time to charge it!)

How do I assign scheduling priorities to each of these competing,
aperiodic, asynchronous tasks?  Priority effectively assigns
"importance" by directing resources (CPU cycles) to one task at
the expense of others.  Which task(s) are more important than
which OTHER tasks?

     "Let's make everything louder than everything else"

No amount of analysis will produce a schedulable task list.  The
system EXPECTS to encounter overload.  It *expects* to miss
deadlines.  Exactly because it can't control the actions of
those things that are interacting *with* it.  And, because it doesn't
have the resources to address the (boundless) overload that is
possible!

I can take a barcode label and rub it vigorously across the barcode
sensor and watch 100% of real time be consumed by that action.
Yet, when my arm eventually gets tired, the system resumes AND
PROVIDES THE CORRECTLY READ LABEL!  Or not.  But, it will NEVER
provide MISREAD data.

Likewise, if any INCOMING characters were missed on either of the
serial ports, the system will know *where* they have been elided
so there is no possibility of a partial message being misinterpreted
as some OTHER *complete* message:

    "You have (not) succeeded!"
               ^^^

[Of course, outgoing character streams are completely unaffeected]

If the user pipettes blood samples into two or more locations
and the system wasn't able to "notice" which came first, it
will not confuse their ordering or fail to notice that *two*
have, in fact, appeared.  The sanctity of the transactions is
preserved regardless of the detail.

The *environment* (user + other equipment) determines the
performance of the system.  Trying to design for a worst case,
UNCONSTRAINED set of activities and task interactions results
in wasteful overprovisioning -- and STILL doesn't guarantee
that everything can get done!

(e.g., add separate processors for all of these "tasks" so that
each is GUARANTEED to be met -- and you'll then discover that
you now have orders of magnitude more data that must be processed
in the same "real time":  what do I *do* with these 400 barcode
read events in the past 3 seconds?  how do they relate to the
numerous blood samples detected?  and the simultaneous database
updates in that same period?)

I excel at making robust *soft* real-time systems -- recognizing
that MOST applications actually *are* "soft", even those that
folks want to THINK of as "hard".  It's just a lot harder to
implement solutions when you *accommodate* missed deadlines than
it is to simply say:  "I *need* the following resources in order to
guarantee that I meet these deadlines" (regardless of whether
they actually *have* to be met in as timely a fashion as suggested)."

This has natural application with aperiodic, asynchronous environments
as you can't "know" when the next deadline (or even release time) will
come along.  You can't *plan* for it.  But, instead, have to *deal*
with it -- AS BEST YOU CAN, given what else may be happening at that
moment.  You might try to model interarrival times of events and
make some assertions based on those assumptions.  But, when Reality
doesn't adhere to your model, you still have to WORK!  You can't
throw up your hands and claim the user is misbehaving!

In my current project, I use a "value function" as the scheduling
criteria:  a tuple that relates (initial) deadline, a notion of value
and a *hard* deadline (at a hard deadline, the task has no continued
value so can be terminated -- and the associated deadline handler
invoked to compensate for its deletion).  This allows *all* tasks
to share a common "criteria system" -- important as tasks can
(physically) "migrate" between nodes and yet retain their "absolute"
scheduling criteria despite the mix of tasks that they will be
competing with on the new node.  The scheduler can dynamically
decide if the "depreciated" value of a task that has missed its
(soft) deadline is still "worth more" than some other task that may
not yet have reached its deadline -- but that has a "slower
depreciation curve" if it *does* miss its deadline as a result of
that scheduling decision.

At the same time, it allows services provided by one task FBO
another to carry the same "significance" on the scheduler instance
that handles the "service" task (because the service task may be
executing on another node).  So, a task's "importance/urgency"
doesn't change just because of the "urgency" of the task that
is CURRENTLY providing a service to it!  Regardless of where that
"service" task happens to be executing at the current time.

Attempting ANY kind of schedulability analysis on a system this
large (thousands of tasks, hundreds of cores) is simply impossible.
All you can hope for is "best effort".

Or, simply concede that it is not possible to design large systems
and limit your efforts to trivial, "provable" ones.

[toc] | [prev] | [next] | [standalone]


#24599

FromNiklas Holsti <niklas.holsti@tidorum.invalid>
Date2016-07-10 17:34 +0300
Message-ID<duf4mpF6hedU1@mid.individual.net>
In reply to#24595
On 16-07-10 12:01 , Don Y wrote:
> On 7/7/2016 1:09 PM, Niklas Holsti wrote:
>> Don Y wrote:
>>> Then, EVERY product that employs a priority-based scheduler should
>>> have a
>>> FORMAL document in part of its deliverables that clearly states these
>>> priorities and the method by which they were derived (as you later call
>>> them "the basis for one important set of the mathematical methods for
>>> verifying real-time performance: schedulability analysis").  So, the
>>> next bloke to look at the code knows exactly why they were chosen and
>>> which assumptions he/she must *continue* to operate under for those
>>> priority assignments to remain valid.
>>
>> Ideally yes, just as every mechanical engineering project should
>> document its
>> design assumptions, stress and strength calculations, etc., and every SW
>> project should deliver full design documentation, complete user manuals,
>> maintenance manuals, etc.
>>
>> But seriously, documentation requirements are a different dimension
>> from the
>> choice of design and implementation methods. Using a systematic design
>> method
>> does not oblige you to document the design, although it makes it much
>> easier to
>> document it.
>
> How can you say that?  Do you expect the next soul to read your mind
> regarding how and why you made specific choices?  Do you expect them
> to retrace your design steps to ensure they understand the assumptions
> you've ENCODED in your choice of priorities?

Design decisions and assumptions resulting in priority assignments are 
no different from design decisions and assumptions resulting in buffer 
sizes, control-loop coefficients, and other kinds of design features. 
You either document them or you don't, depending on your customers' 
requirements and on your own quality standards.

> Or, are they free to change your priorities WITH NO EFFECT ON THE
> RESULTING IMPLEMENTATION?

Just as free as they are to change buffer sizes and control-loop 
coefficients. They either know what they are doing (helped by 
documentation, if it exists) or don't know what they are doing. As I've 
said, all my day-job projects deliver extensive design documentation, 
including SW Budget Reports with task priorites and their motivations.

> But, I am careful to document how and why each of these mechanisms
> are used and "prove" that they *can't* run amok in my description
> of the algorithms, etc.  And, the assumptions that dictate how
> future uses/adaptations must operate.

Good for you and your customers. I hope they pay you for it, too. I 
suspect that for many mass-market products the customer (i.e. the entity 
who subcontracts SW development) only cares that the SW works, but is 
not interested in its design details.

>>> Ask yourself how many of those documents you've seen?  Authored?
>>
>> Several, for both questions. All the day-job projects I work on have
>> such, and
>> I am usually the author.
>
> I suspect you are in the minority as (IME) most folks using priority
> based schedulers just "pick numbers" and, later, "tweek them" to make
> their design work properly.  Usually, with little formal knowledge of
> the limitations of the algorithms or the problems that can manifest
> (nor the potential solutions *or* the problems with the solutions!)
>
> Would you care to share any of those rationales?

As I have said, I usually rely on deadline-monotonic priority assignment 
and its response-time analysis. There is a huge literature on scheduling 
methods and schedulability analysis methods, for hard real-time systems, 
soft real-time systems, and mixtures. I know only a little bit about the 
hard-real-time part and almost nothing about the soft-real-time part. In 
my day-job projects, the soft-real-time part is non-critical and is 
validated by stress tests on practical-worst-case test scenarios agreed 
with the customer.

> I'm hosting a course
> that presents various OS design techniques, scheduling algorithms,
> hazzards, etc. and examples of how to (and NOT to) exploit each later
> this Fall.  "Fabricating" artificial examples always *feels* like an
> artifice; presenting REAL examples allows folks to see ACTUAL tradeoffs.

If this is about server operating systems, with an unpredictable mix of 
batch, interactive, and network/transaction applications, it's a 
different ball-game. And mobile handsets are more and more coming to 
resemble such servers, with the profusion of applications of every 
possible nature. I have no contributions to make in those domains.

Where will this course be given? Will it be on the net, perhaps as a MOOC?

> And, I suspect, your tasks are largely *periodic*?  And/or orthogonal to
> each other?

The hard-real-time tasks tend to be periodic, but sporadic ones also 
occur. The softer tasks are usually sporadic.

Configuration parameters and commands usually flow from the 
soft-real-time part to the hard-real-time part, and the hard-real-time 
part usually generates data into buffers that are emptied by the 
soft-real-time part. Rather typical control & measurement systems.

The most common complex task interaction is a communication channel 
shared by several tasks. For example, a hard-real-time task may be 
communicating cyclically over the channel, while some soft-real-time 
tasks must use the same channel for sporadic communications.

> I have had exactly one project in 40 years of RT design that fit that
> mold -- a process that ran at 200Hz (5ms cycle time) with "hard"
> deadlines (in the sense that a deadline missed resulted in a failure
> of that *cycle* of the process -- a "defective product" to be discarded).
> Note that missed hard deadlines didn't indicate a failed *implementation*!
>
> By and large, my projects have consisted of aperiodic, cooperating
> tasks driven by "semi-random processes"; processes that can't be easily
> quantified nor constrained!  And, running on under-provisioned hardware.
>
> E.g., the example up-thread has a bunch of user I/O's:
> - barcode reader
> - two serial ports
> - keypad
> - sensor array
> - display
> - audio annunciator (sound synthesizer)
>
> There is nothing I can do to prevent a user from scanning a barcode
> label at *any* time in the normal operation of the system.  I.e.,
> "bars" (not "labels") can arrive for processing at any time.  That's
> part of the *appeal* of the system -- the USER drives it instead
> of *it* driving the user!

   [snip]

If you have decided that static priorities, or some other specific 
scheduling principles, don't work for you in this application, fine, use 
something else. But IME static priorities do work for many other 
applications.

> How do I assign scheduling priorities to each of these competing,
> aperiodic, asynchronous tasks?  Priority effectively assigns
> "importance" by directing resources (CPU cycles) to one task at
> the expense of others.  Which task(s) are more important than
> which OTHER tasks?

Again you confuse "importance" with "urgency". For example, some inputs 
have HW buffers (FIFOs), some have not; typically processing the 
buffered inputs is less urgent than the unbuffered inputs. Or you can 
provide a SW buffer, filled by an interrupt handler, for an input that 
does not have a HW buffer, and correspondingly relax the urgency of the 
task reading the SW buffer.

If you are saying that all *inputs* are equally urgent, fine, poll them 
all in a single task and delegate the input data processing to other 
tasks in order of urgency of the *outputs*. If you think that all the 
outputs are equally urgent, too, then do everything in a single task -- 
the "Task Loop" in our Subject.

> No amount of analysis will produce a schedulable task list.  The
> system EXPECTS to encounter overload.

In priority-based systems, the typical solution to overload is to 
implement load-refusing mechanisms such as ignoring interrupts that are 
too close together. Whether this can be made to work well enough for the 
application to react gracefully under overload depends on the system 
design (including the HW design).

>  It *expects* to miss deadlines.  Exactly because it can't control
> the actions of those things that are interacting *with* it.

The SW can control the rate at which it accepts inputs for processing.

> The *environment* (user + other equipment) determines the
> performance of the system.

The environment always determines the offered load. In case of overload, 
depending on the robustness requirements of the SW the SW may be allowed 
to fail severely or be required to degrade gracefully. Apparently in the 
system you describe the latter case obtains, but then the proper design 
depends on the precise definition of "gracefully".

> I excel at making robust *soft* real-time systems -- recognizing
> that MOST applications actually *are* "soft", even those that
> folks want to THINK of as "hard".

If a specific graceful handling of overloads is required then I agree 
that the system acquires soft-real-time aspects. But some hard-real-time 
aspects may remain, if overload is still considered an anomaly. If the 
load that you call "overload" is actually expected, I would not call it 
"overload" at all, just a load for which all inputs cannot be processed 
in the same way as under lesser loads.

> In my current project, I use a "value function" as the scheduling
> criteria:  a tuple that relates (initial) deadline, a notion of value
> and a *hard* deadline (at a hard deadline, the task has no continued
> value so can be terminated -- and the associated deadline handler
> invoked to compensate for its deletion).

As I said, I know almost nothing about soft-real-time scheduling, but I 
remember seeing published papers with similar methods: value functions 
that depend on the elapsed time of a computation or the expected time of 
delivery of the result. I don't doubt that they can work, even if the 
definition of such value functions seems to me more problematic and 
ad-hoc than the definition of priority.

> Attempting ANY kind of schedulability analysis on a system this
> large (thousands of tasks, hundreds of cores) is simply impossible.
> All you can hope for is "best effort".

Soft-real-time "schedulability" analyses usually focus on maximising the 
total "value" delivered or the overall Quality of Service, not on 
computing or minimising worst-case response times.

> Or, simply concede that it is not possible to design large systems
> and limit your efforts to trivial, "provable" ones.

As I think I've said in some earlier post, IMO for hard-real-time 
systems the analysability limit comes from the increasing complexity of 
task interactions in large systems. That can be combated with better 
modular design and with systematic task interaction patterns.

While small systems may be "trivial" from an academic point of view, 
there are certainly applications that are small enough to be provably 
analysed but still are non-trivial in terms of importance and value to 
the customers.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

[toc] | [prev] | [next] | [standalone]


#24635 — Re: Common name for a "Task Loop" [long]

FromDon Y <blockedofcourse@foo.invalid>
Date2016-07-17 01:17 -0700
SubjectRe: Common name for a "Task Loop" [long]
Message-ID<nmfeu7$pbn$1@dont-email.me>
In reply to#24599
On 7/10/2016 7:34 AM, Niklas Holsti wrote:
> On 16-07-10 12:01 , Don Y wrote:
>> On 7/7/2016 1:09 PM, Niklas Holsti wrote:
>>> Don Y wrote:
>>>> Then, EVERY product that employs a priority-based scheduler should
>>>> have a
>>>> FORMAL document in part of its deliverables that clearly states these
>>>> priorities and the method by which they were derived (as you later call
>>>> them "the basis for one important set of the mathematical methods for
>>>> verifying real-time performance: schedulability analysis").  So, the
>>>> next bloke to look at the code knows exactly why they were chosen and
>>>> which assumptions he/she must *continue* to operate under for those
>>>> priority assignments to remain valid.
>>>
>>> Ideally yes, just as every mechanical engineering project should
>>> document its
>>> design assumptions, stress and strength calculations, etc., and every SW
>>> project should deliver full design documentation, complete user manuals,
>>> maintenance manuals, etc.
>>>
>>> But seriously, documentation requirements are a different dimension
>>> from the
>>> choice of design and implementation methods. Using a systematic design
>>> method
>>> does not oblige you to document the design, although it makes it much
>>> easier to
>>> document it.
>>
>> How can you say that?  Do you expect the next soul to read your mind
>> regarding how and why you made specific choices?  Do you expect them
>> to retrace your design steps to ensure they understand the assumptions
>> you've ENCODED in your choice of priorities?
>
> Design decisions and assumptions resulting in priority assignments are no
> different from design decisions and assumptions resulting in buffer sizes,
> control-loop coefficients, and other kinds of design features. You either
> document them or you don't, depending on your customers' requirements and on
> your own quality standards.

As damn near everything I've worked on has had to see others
support/maintain it after me, NOT documenting design issues has
significant (often serious) consequences.

You can't count on the next soul to have the same grasp of the complexity
of a particular *portion* of an implementation that you had when you
*designed* it, in the context of the rest of the application/system.
(And this assuming there are formal specifications available!)
Esp when that soul is probably just pushed at a particular "problem",
*cold*:  "Fix this", "Add this feature", etc.  "And, can you have
it done before lunch??"

I've taken to preparing "tutorials" for various algorithms to give the
next guy a quickie education on the issues involved -- as "comments"
in code don't go far enough to address the sort of background
information that is often required.  And, are generally limited
to *text* (e.g., no illustrations, animations, etc.  How do I
describe the "creakiness" parameterization of a voice "in words"?
OTOH, "click on this to hear an example of creakiness... Now, tweak
this control and click, again!")

This allows my code to be skimpier on comments -- because it can
reference issues that are explained more fully, in those documents.

It also frees me from having to keep tweeking those comments
as I make subtle changes in the implementation.

And, lets me put truly important reminders in the code.  E.g.,
you will frequently encounter "Here, there be dragons" -- as a
warning that the implementation is intentionally the way it is;
resist the urge to "optimize" or "simplify" it... because there
are issues at stake that such changes will inevitably break.
Often without being immediately noticeable!  I.e., make SURE
you've read the accompanying information and understand what's
at stake before you go twiddling bits!

I also like to litter my code with numerous invariants -- to make
it crystal clear what can be expected at each point in the code
(even if the invariants are just "pseudo-code").  Usually, these have to
be elided (e.g., implemented with #ifdef DEBUG) from the production code
(as they represent the worst kind of "dead code")

>> Or, are they free to change your priorities WITH NO EFFECT ON THE
>> RESULTING IMPLEMENTATION?
>
> Just as free as they are to change buffer sizes and control-loop coefficients.
> They either know what they are doing (helped by documentation, if it exists) or
> don't know what they are doing. As I've said, all my day-job projects deliver
> extensive design documentation, including SW Budget Reports with task priorites
> and their motivations.

And your "mathematical proof/analysis"?  I.e., can someone *verify*/validate
your design based on your documentation?

If I set aside N bytes for a buffer, there is a justification for that
choice in the comments or accompanying descriptions.  So, if that
rationale doesn't stand the test of time (i.e., assumptions change),
the guy after me knows how he should go about determining the new
value.

>> But, I am careful to document how and why each of these mechanisms
>> are used and "prove" that they *can't* run amok in my description
>> of the algorithms, etc.  And, the assumptions that dictate how
>> future uses/adaptations must operate.
>
> Good for you and your customers. I hope they pay you for it, too. I suspect
> that for many mass-market products the customer (i.e. the entity who
> subcontracts SW development) only cares that the SW works, but is not
> interested in its design details.

For products that have no "maintenance cycle", that may be the case.
But, for medical instruments, pharmaceutical systems, process
control systems, etc. there is often MORE cost in the validation
than the "development".  Having lots of documentation often helps
with "due diligence" defenses, etc.  It goes to addressing concerns
that the design may have been sloppy, intentionally negligent, etc.

     "Did you consider this?"
     "Yes -- and this is the analysis that was performed..."

And, anything that hopes to be extensible *must* be documented;
you don't want to discourage those extensions by effectively
obfuscating your design!  Otherwise, why KEEP the source code
if you don't expect others to look at it!

You, instead, want people to be able to come up to speed and understand
your design methodology without HOPING it jumps off the page (code)
at them.

>>>> Ask yourself how many of those documents you've seen?  Authored?
>>>
>>> Several, for both questions. All the day-job projects I work on have
>>> such, and
>>> I am usually the author.
>>
>> I suspect you are in the minority as (IME) most folks using priority
>> based schedulers just "pick numbers" and, later, "tweek them" to make
>> their design work properly.  Usually, with little formal knowledge of
>> the limitations of the algorithms or the problems that can manifest
>> (nor the potential solutions *or* the problems with the solutions!)
>>
>> Would you care to share any of those rationales?
>
> As I have said, I usually rely on deadline-monotonic priority assignment and
> its response-time analysis. There is a huge literature on scheduling methods
> and schedulability analysis methods, for hard real-time systems, soft real-time
> systems, and mixtures. I know only a little bit about the hard-real-time part
> and almost nothing about the soft-real-time part. In my day-job projects, the
> soft-real-time part is non-critical and is validated by stress tests on
> practical-worst-case test scenarios agreed with the customer.

You're taking the attitude of "if its HRT, then I can claim 'I need...'".

I argue that much HRT isn't truly necessary to be implemented in that
fashion.  (I'm speaking with no knowledge of your particular application
domain -- just years of experience watching people treat things as
"hard" requirements that needn't be.)  The suggestion that "soft" is
therefore "not as important" is a foolish distinction, IME.

    "Hard real-time is hard; SOFT real-time is HARDER!"

Yet, there's no inherent guarantee that those tests actually stress
the things they *should* stress.  You've just got a "legal defense"
(contractual) but haven't ensured the product does what it *should*.

E.g., the spirit rover, I'm *sure*, had a boatload of testing and simulation
before it was ever loaded into the nose cone of that rocket...

>> I'm hosting a course
>> that presents various OS design techniques, scheduling algorithms,
>> hazzards, etc. and examples of how to (and NOT to) exploit each later
>> this Fall.  "Fabricating" artificial examples always *feels* like an
>> artifice; presenting REAL examples allows folks to see ACTUAL tradeoffs.
>
> If this is about server operating systems, with an unpredictable mix of batch,
> interactive, and network/transaction applications, it's a different ball-game.
> And mobile handsets are more and more coming to resemble such servers, with the
> profusion of applications of every possible nature. I have no contributions to
> make in those domains.

No, I'm simply offering a smorgasbord of exposures to different technologies
for folks who've typically never had any formal training on the material;
they're victims of the "heard it at the water cooler" approach that is so
common in the industry; or, "read a 2 page description in a trade magazine".
People not keeping up with technology and theoretical work in the (mistaken)
assumption that "they, *themselves*, actually DO this and are, thus, The
Experts".

Would you bring your wife to a doctor who thought the treatment for
breast cancer was radical mastectomy?  (as it ONCE *was*)  Or, would
you find someone who is "keeping current" with the best practices in
their trade/industry?

> Where will this course be given? Will it be on the net, perhaps as a MOOC?

No, it's a local/private gathering for friends/colleagues.  It
was suggested to video tape them and make YT videos but I've
argued against that as it alters the way in which I can present the
material.  I've opted for a "lab" approach:  write some code to solve
this "trivial" problem; now, let's show you how easy it is to BREAK
that code as it interacts with other tasks, unexpected events
in the environment, etc. -- the sorts of things you MAY or may NOT
encounter before formal release... but, that are problematic areas
in your design!  Because you "hand-waved" important design issues
instead of approaching them as ENGINEERING tasks.

>> And, I suspect, your tasks are largely *periodic*?  And/or orthogonal to
>> each other?
>
> The hard-real-time tasks tend to be periodic, but sporadic ones also occur. The
> softer tasks are usually sporadic.
>
> Configuration parameters and commands usually flow from the soft-real-time part
> to the hard-real-time part, and the hard-real-time part usually generates data
> into buffers that are emptied by the soft-real-time part. Rather typical
> control & measurement systems.

Yes.  Address the "(sub)tasks" with the strictest deadlines "in hardware"
(e.g., the foreground).  Then, let the remaining tasks "consume" (and
produce) as resources are available.

How do you know the SRT tasks *will* empty the buffers before the HRT
tasks need to refill them?  etc.

E.g., my barcode reader ISR filling its buffers as bras/spaces pass
the sensor... *hoping* the background tasks can clear out the old
data before the newest needs that space!

> The most common complex task interaction is a communication channel shared by
> several tasks. For example, a hard-real-time task may be communicating
> cyclically over the channel, while some soft-real-time tasks must use the same
> channel for sporadic communications.
>
>> I have had exactly one project in 40 years of RT design that fit that
>> mold -- a process that ran at 200Hz (5ms cycle time) with "hard"
>> deadlines (in the sense that a deadline missed resulted in a failure
>> of that *cycle* of the process -- a "defective product" to be discarded).
>> Note that missed hard deadlines didn't indicate a failed *implementation*!
>>
>> By and large, my projects have consisted of aperiodic, cooperating
>> tasks driven by "semi-random processes"; processes that can't be easily
>> quantified nor constrained!  And, running on under-provisioned hardware.
>>
>> E.g., the example up-thread has a bunch of user I/O's:
>> - barcode reader
>> - two serial ports
>> - keypad
>> - sensor array
>> - display
>> - audio annunciator (sound synthesizer)
>>
>> There is nothing I can do to prevent a user from scanning a barcode
>> label at *any* time in the normal operation of the system.  I.e.,
>> "bars" (not "labels") can arrive for processing at any time.  That's
>> part of the *appeal* of the system -- the USER drives it instead
>> of *it* driving the user!
>
>    [snip]
>
> If you have decided that static priorities, or some other specific scheduling
> principles, don't work for you in this application, fine, use something else.
> But IME static priorities do work for many other applications.

I'm not saying they *can't* work.  What I am saying is that people
employ "RTOS's" (COTS or homegrown) and inevitably end up with a
"priority based scheduler" (i.e., small integers) and they *pick*
priorities based on "feel".  Or, some other notion of what they
should "mean".  Then, jigger them when those assumptions prove to
be false given the task partitioning that they've ALREADY adopted.

[They're unlikely to refactor the design; MORE likely to jigger
the priorities, run it "for a while" to reassure themselves that
"it works" -- and then extrapolate that experience on the bench to
experience in the field!
   "I put in a 2A fuse and it didn't blow. Therefore, the load will
   never exceed 2A!"
(reread that statement to realize how silly it sounds -- esp as a
design technique!  I.e., the fact that it didn't blow somehow
ENSURES that it won't!) Just because your code *appeared* to work in
the lab, doesn't mean it will continue to work!  So, *prove* to
me -- in your design review -- that your "scheduling criteria"
(whatever they might be) ensures that these things WILL get executed;
*OR*, show me how you will handle the cases where they DON'T!]

When something "misbehaves", if they can't easily find an
explanation -- and, if it doesn't *repeatedly* misbehave -- they
shrug and write it off as a "fluke".  As if this one time event
was a "can't happen" (yet, it DID!  I.e., some assumption that
you have made in your design has now PROVEN to be wrong!  YOU
SAW IT HAPPEN!!  Do you think this was a stray alpha particle?
Power supply ripple?  Gremlins??)

I designed an autopilot for a boat ~35 years ago.  It used LORAN-C
navigation signals to pilot the boat to a particular spot on the globe
(latitude,longitude) -- compensating for oceanic currents, etc.

On its maiden voyage, we took it around Cape Cod (Massachusetts)
<https://upload.wikimedia.org/wikipedia/commons/b/bc/Cape_Cod_Landsat_7.jpg>
using the coordinates of buoys "in open water" to define the
individual legs of the trip (kinda hard to know FOR SURE where
you are in open water -- there aren't a lot of street signs you
can consult!  :> ).  Our track was recorded (on paper) via a LORAN-C
position plotter.  So, we could document our travels wrt the coastline
(indicated on the *map* that had been used as a drawing surface).

On one leg of the trip, a very pronounced 'S' was visible in the
track; as if the boat had turned 90 degrees off course, then
compensated by making a "U-turn, then overshot the original
track and made another "U-turn", then turning 90 degrees to
get BACK onto the original track!

Sure *sounds* like some sort of "divide by zero" bug!  Or,
something equally bizarre to cause such a sharp set of
discontinuities in our track!

I was never able to find an "explanation" for this behavior
in the code.  Despite a careful analysis of my algorithms,
the floating point library, etc.  (of course, I don't have
records of the raw data on which my algorithms operated...)

My boss explains it as the point at which we stopped to do
some deep sea fishing.  The boat would twist and turn as
the currents kept trying to align the vessel with the
incoming waves (so the waves would strike the boat broadside
instead of at the bow).  So, the skipper had to periodically
turn the boat to bow or stern would be into the current.

Those being exactly the "right angles" noticed in the plot!

While this is PROBABLY true, I still drag out those sources
periodically in the hope of stumbling on something that would
be a more *provable* explanation (even though it would have
to be a BUG!)

>> How do I assign scheduling priorities to each of these competing,
>> aperiodic, asynchronous tasks?  Priority effectively assigns
>> "importance" by directing resources (CPU cycles) to one task at
>> the expense of others.  Which task(s) are more important than
>> which OTHER tasks?
>
> Again you confuse "importance" with "urgency".

Because it *is* "importance" and not "urgency".  Urgency tends to
conjure up images of "immediacy".  As if a deadline 5 seconds hence is
more urgent than a deadline 5 hours hence.

That distorts the "importance" of the two situations.

If you have a poor selection of food choices in the house, a trip to the
grocery store "before dinner" (an hour hence) may seem "most urgent".
However, if your vehicle is up on blocks, awaiting repairs, *that*
may be the "more important" undertaking; eat some cheese and crackers
(or, go hungry for a meal or two -- it won't KILL you!) so you can,
instead, devote your time to getting the car repaired (even though
the "deadline" is DAYS away -- driving it to work Monday morning!
It may well take you ALL of that time to get it running!)

Algorithms like EDF assume all tasks have equal "importance" (value)
and, favor those with the "soonest" deadlines (by assuming that all
deadlines *can* be met!).  LST, by contrast, favors tasks that
have the "smallest margins (for timing errors)".  "Priority" allows
some arbitrary "small integer" to codify the scheduling needs.

None of these address the relative "importance" of a particular
undertaking.

E.g., you can afford to live on cheese and crackers for a few meals
*if* it allows you to drive to work Monday morning.  The alternative
is a richer set of meal choices, in the short term, followed by
a bus/cab ride to work, Monday!  (more costly and inconvenient *and*,
risks your not meeting some OTHER goals, Monday afternoon, because
you had to wait for a bus to get you back to the house... and you
STILL have to finish work on the car for TUESDAY morning's trip.
But, you'll be able to eat STEAK, *again*, for Monday supper...  :< )

> For example, some inputs have HW
> buffers (FIFOs), some have not; typically processing the buffered inputs is
> less urgent than the unbuffered inputs. Or you can provide a SW buffer, filled
> by an interrupt handler, for an input that does not have a HW buffer, and
> correspondingly relax the urgency of the task reading the SW buffer.
>
> If you are saying that all *inputs* are equally urgent, fine, poll them all in
> a single task and delegate the input data processing to other tasks in order of
> urgency of the *outputs*. If you think that all the outputs are equally urgent,
> too, then do everything in a single task -- the "Task Loop" in our Subject.

You can't "poll" for incoming characters from a UART without risking
encountering many "receiver overrun" errors.  You can't poll for
black-to-white (or white-to-black) transitions on a photodetector
input (at a nominal 8KHz) and expect to "see" them all.  You
can't poll a bunch of high frequency oscillators to note how
their frequencies are changing in response to actions from the user.

All of this data acquisition has to happen "in hardware" -- but,
very *little* hardware.  E.g., the barcode "video" just effectively
captures the time of a free-running counter into a latch (that
latch being a software "read" instruction executing in an ISR).
If you *miss* it, it's gone.  And, the barcode label in which it
occurred can now NOT be decoded:  "Sorry, user, could you please
try that again?  Ooops!  Damn!  One more time... I was busy
polling a UART that time...  (sigh)  And, yet again... I got
distracted by the audio annunciator on that last attempt..."

Because there are no constraints on what the *user* can choose to do,
you have to be ready and able to "see" whatever he chooses to do
WHEN he chooses to do it.  Everything is "equally important".
(I.e., he doesn't push a button to say, "I am now going to
scan a barcode label.  Please activate the barcode reading task
and suspend any other tasks that might be competing with it for
resources... I *promise* I won't do anything that you SHOULD
see unless I *tell* you that I will be doing it!")

As I' like to say, tongue-in-cheek:
     "Let's make everything louder than everything else"
(IIRC, Deep Purple?)

Instead, you ensure nothing "gets by you", unnoticed.  It might
not be recognized/processed.  But, it MUST be "noticed".  You
have to KNOW that you've "missed something".  Because, you
have to know that you have NOT missed ANYTHING when you make
claims about the transactions that you are monitoring and the
data that you are maintaining:

     "I *know* the message I received was 'deploy the warhead'
     and *not* 'do NOT deploy the warhead' -- because I didn't
     *miss* anything during its reception!"

Or, conversely:

     "I'm sorry, I can't vouch for the integrity of the
     PORTION of the message that I THINK I received because
     I *know* parts of it were missed..."

>> No amount of analysis will produce a schedulable task list.  The
>> system EXPECTS to encounter overload.
>
> In priority-based systems, the typical solution to overload is to implement
> load-refusing mechanisms such as ignoring interrupts that are too close
> together. Whether this can be made to work well enough for the application to
> react gracefully under overload depends on the system design (including the HW
> design).

You're still "picking winners" (and, thus, losers).  Which of the above tasks
should have which priorities?  Assigning priorities effectively assigns
"importance".  If I let the scheduler favor the barcode decoding task
(in the background, forget the foreground role), then that implies that
decoding barcodes are more important than servicing data requests on the
UARTs.  Or, detecting blood sample/reagents placed in the sensor array.

Even if scanning a barcode is meaningless at this point in time!
(I can't reach out and grab the user's arm or drop a shutter
over the photodetector!)

>>  It *expects* to miss deadlines.  Exactly because it can't control
>> the actions of those things that are interacting *with* it.
>
> The SW can control the rate at which it accepts inputs for processing.

That just says, "the software can decide how much it wants to MISS".
But, it still has *missed* those things!  I can't reach out and
stay the hand of a user who is preparing to swipe a barcode label
passed the photodetector.  I can turn off the ISR that services it
(or, kill the task that would decode it), but when do I turn it
back on?  How happy will the user be that he scanned a label
and the system didn't "see" it?

I can turn off the Rx ISR for the UARTs.  I can drop the handshaking
signals to tell the remote device(s) to stop sending.  But, that
doesn't mean they will.  Or, will as promptly as I *hope* they
will (how quickly will an unknown piece of equipment respond to
an XON/XOFF?  Modem control signals?  Will they *know* that I
may not have seen some action that they took on that interface?
Will they stall waiting for an acknowledgement that will NEVER come?
When they reissue the request, will I coincidentally repeat this
same action -- leading to yet another interface stall?

When will the customer consider the system to be performing
badly?  How will he know what *he* can do to change that?
How much MORE hardware should the system include to address the
needs of *some* users -- yet STILL not be "foolproof"?

>> The *environment* (user + other equipment) determines the
>> performance of the system.
>
> The environment always determines the offered load. In case of overload,
> depending on the robustness requirements of the SW the SW may be allowed to
> fail severely or be required to degrade gracefully. Apparently in the system
> you describe the latter case obtains, but then the proper design depends on the
> precise definition of "gracefully".

You let the user define what is acceptable by altering his interactions
with the system to obtain the "best" performance for his particular needs.

If a user only has one device connected to the UARTs, then less "real time"
will be consumed servicing UARTs.  If a user manually types identifiers
in via the keyboard, then less "real time" will be consumed scanning
barcodes.  Etc.

It's silly of the device to DICTATE to the user how it should be used.

And, few would want to *pay* for the hardware and software that can address
ANY set of needs, regardless of THEIR *particular* set of needs!

>> I excel at making robust *soft* real-time systems -- recognizing
>> that MOST applications actually *are* "soft", even those that
>> folks want to THINK of as "hard".
>
> If a specific graceful handling of overloads is required then I agree that the
> system acquires soft-real-time aspects. But some hard-real-time aspects may
> remain, if overload is still considered an anomaly. If the load that you call
> "overload" is actually expected, I would not call it "overload" at all, just a
> load for which all inputs cannot be processed in the same way as under lesser
> loads.
>
>> In my current project, I use a "value function" as the scheduling
>> criteria:  a tuple that relates (initial) deadline, a notion of value
>> and a *hard* deadline (at a hard deadline, the task has no continued
>> value so can be terminated -- and the associated deadline handler
>> invoked to compensate for its deletion).
>
> As I said, I know almost nothing about soft-real-time scheduling, but I
> remember seeing published papers with similar methods: value functions that
> depend on the elapsed time of a computation or the expected time of delivery of
> the result. I don't doubt that they can work, even if the definition of such
> value functions seems to me more problematic and ad-hoc than the definition of
> priority.

The "value" of the approach is that it lets the scheduler make the
tradeoff, dynamically.  I *know* how "valuable" (important) a
particular scheduling option is, *now*.  I also know when it has NO
value!

In your systems, you appear to split things into two groups:
those that MUST meet their deadlines and those that "don't have to".
You call these HARD and SOFT, respectively.

If a HARD task misses its deadline, you (appear to?) consider that
a system failure.  Your product is broken.  Presumably, there is
also some point at which you consider a postponed SOFT task to
also be indicative of a failure (I assume you aren't willing
to leave a task eligible "forever" without expecting some
progress towards its goal?).

In my world, every task has two deadlines (and a "value").
The first ("soft") deadline is the desired target.  Maximum
(system) value ("usefulness") is (typically) achieved by
meeting these deadlines for all tasks.

[I assume a particular "shape" of value function that isn't
necessarily applicable to ALL types of real-time systems]

The second ("hard") deadline is the point at which any
further effort/resources expended by the task is "useless".
BUT, this doesn't imply that the product is *broken*!
Rather, that the task's role in the product is no longer
of interest to justify expending additional resources on
attaining its goal(s).  Kill the task and free the resources.
Why steal those from OTHER tasks that might still be able
to meet *their* deadlines, once you are out of the picture?!

What "priority" should an audible keystroke feedback indication
be?  How "urgent"?  What should the system risk NOT accomplishing
in order to make a silly little "click/beep" sound on each keystroke?

Ideally, that should be within milliseconds of the key being
*pressed* (i.e., not when it is RECOGNIZED but, rather, when it
is PRESSED!  Artificially HIGHER "priority"!).  Yet, in the
grand scheme of things, the user probably cares little about
it!  It's not like he's likely to say, "Hey!  I didn't get a
keyclick for that last keystroke -- even though I can SEE that
it was recognized by the appearance of the associated digit
in the display..."

So, there is a point at which any work towards making that keyclick
is just waste.  And, can even be distracting.  Kill the job and move
on.

[The classic example is bottles on an ever-moving conveyor;
once a bottle has past a certain point, any efforts to
position a "picking arm" to grasp it and convey it to
an alternate location are wasted!  The bottle *will* crash
to the floor.  There will be some cost to this "missed
deadline" (i.e., a broken bottle).  Wasting resources to
try to "catch it as it falls" could put the *next* bottle
at jeopardy.  Etc.  It may be more prudent to just accept that
occasional loss (perhaps the arm mechanism bound up during
this cycle resulting in the *intermittent* failure) and
get back into stride than risk prolonging the "disturbance".]

At the same time, the deadline handler for the (abandoned!)
task is scheduled for execution.  *It* can then apply
the "consequences" of this missed HARD deadline.  Maybe
just increment a "broken bottle counter".  Or, shut down
the production line because "too many" bottles have broken
in too short an interval ("Maintenance" needs to look at the
mechanism to see why it has been misbehaving at a statistically
higher rate than in days passed).

The grey area between soft and hard deadlines is where the
scheduler can "add the most value" (tongue-in-cheek).

Should it chase after that bottle that has slipped past the
"picker" and possibly save it from crashing to the floor?  Or,
should it visually examine the label on the *next* bottle to
ensure that *it* is positioned properly?  ("quality")

In some scenarios, you could argue for having the picker chase
the bottle as that can "save" on an otherwise material loss.
Especially if the "other" bottle can summarily be routed to a
"manual label verification" station (where a human operator
reexamines the label placement and removes and replaces it,
if necessary, before reintroducing the bottle to the ass'y
line).

In another scenario, the labor involved in inspecting and/or
reapplying labels might be so high that it's cheaper to let
a bottle fall to the floor (or, into a cushioned bin placed
there to address these deadline overruns!) than it is to
run yet another bottle through the manual label inspection
process!

You can't do this with "priorities".  Something has to be able to
dynamically REASSIGN priorities, on the fly, in order for a
scheduler to know how to choose.

>> Attempting ANY kind of schedulability analysis on a system this
>> large (thousands of tasks, hundreds of cores) is simply impossible.
>> All you can hope for is "best effort".
>
> Soft-real-time "schedulability" analyses usually focus on maximising the total
> "value" delivered or the overall Quality of Service, not on computing or
> minimising worst-case response times.

That depends on how you define that "value".  If value is correlated
to "inverse lateness", then maximizing value inherently *minimizes*
lateness.

>> Or, simply concede that it is not possible to design large systems
>> and limit your efforts to trivial, "provable" ones.
>
> As I think I've said in some earlier post, IMO for hard-real-time systems the
> analysability limit comes from the increasing complexity of task interactions
> in large systems. That can be combated with better modular design and with
> systematic task interaction patterns.

It is a separate issue from hard vs. soft.  The number and nature of
the modules and their interconnectedness is what drives the (lack of)
"analyzability".  I can create a system with hundreds of hard (or
soft) RT tasks that is trivially analyzable:  make all of the tasks
orthogonal to each other; ensure the sum of their processing times
is less than the time to the *first* deadline.  I.e., you don't even have
to take out a pen and paper to KNOW that this system is schedulable
(with ANY algorithm!)

OTOH, think of a system with a "few" tasks that are heavily interrelated
(due to the nature of the application) and you can spend considerable
effort convincing yourself (and others) of its schedulability under any
*particular* algorithm, let alone picking the *best* algorithm.

> While small systems may be "trivial" from an academic point of view, there are
> certainly applications that are small enough to be provably analysed but still
> are non-trivial in terms of importance and value to the customers.

I've not said or implied otherwise!  A traffic light controller is
both "trivial" (conceptually) and "complex" (in actual implementation).
Yet, no one would dispute its utility!

[toc] | [prev] | [next] | [standalone]


#24570

FromTim Wescott <seemywebsite@myfooter.really>
Date2016-07-07 16:02 -0500
Message-ID<2oidnf2F7JgfXuPKnZ2dnUU7-LWdnZ2d@giganews.com>
In reply to#24567
On Thu, 07 Jul 2016 21:36:29 +0300, Niklas Holsti wrote:

> On 16-07-07 09:16 , Don Y wrote:
>> On 7/6/2016 9:50 PM, George Neuner wrote:
>>> On Wed, 6 Jul 2016 21:37:12 +0300, Niklas Holsti
>>> <niklas.holsti@tidorum.invalid> wrote:
>>>
>>>> On 16-07-06 13:06 , Don Y wrote:
>>>>
>>>>> As I said before, priorities tell you nothing about the timeliness
>>>>> constraints of tasks.  You can just as well give them names of
>>>>> fruits and vegetables and rank them using whatever criteria *seems*
>>>>> to work, today...
>>>>
>>>> I think you are looking at priorities from the wrong perspective -- a
>>>> too high-level perspective.
>>>>
>>>> Task priorities are a design and coding mechanism, of the same nature
>>>> as procedures, statements, while-loops, if-then-else statements, and
>>>> so on.
>>>> Just as if-then-else statements let the designer tell the processor
>>>> which of two statements should be executed, depending on some
>>>> application-specific condition, so priorities let the designer tell
>>>> the RTOS scheduler which of two tasks/threads should be executed in
>>>> preference to the other, depending on some implementation-specific
>>>> analysis or priority assignment rules.
>>>
>>> I think Don's point is that task priorities are merely a proxy for the
>>> actual scheduling criteria - whatever that may be.
>>
>> Exactly.  "Priority" (in the sense of "set_task_priority()") is just an
>> expedient to make coding a scheduler easy.  It tells you *nothing*
>> about the task's "importance", "timeliness constraints", etc.
> 
> That is not so, if you follow a systematic and proven
> priority-assignment rule. For example, if you use deadline-monotonic
> priorities then the order of task priorities is equivalent to the order
> of task deadlines (expressed as the maximum duration between task
> activation and completion). So then the task priorities certainly tell
> you a lot about the (relative) timeliness constraints.
> 
> If you just assign priorities based on some subjective "task importance"
> feeling, your statement is valid.
> 
>> The advantage to deadlines (if we can avoid the RT taint) is that they
>> are "portable" -- a description of a deadline in a particular
>> application can be related DIRECTLY to a deadline in some completely
>> unrelated application:  they share an axis and unit of measure!
> 
> Yes, and priorities can represent deadlines, see above, in which case
> priorities are portable, too.
> 
>> "Priority" (in the "set_task_priority()" sense) is just a completely
>> bogus number that ONLY means something in the context of the PARTICULAR
>> set of tasks that it is currently bound.
> 
> Priorities are instructions to the scheduler. I agree that they have
> meaning only for a particular task set, because they represent only the
> *relative* scheduling preferences between the tasks in this set.
> 
>> Is "2" twice as "important" as "1"?  Half as "important" as "4"?
> 
> Those are meaningless questions. Priorities are an ordinal scale, not an
> interval or ratio scale
> (https://en.wikipedia.org/wiki/Statistical_data_type).
> 
>> The folly of "priority" (set_task_priority) in scheduling is
>> illustrated in my immediately preceding example:  why don't other
>> actors performing services on behalf of a task "having" (executing at)
>> priority 'P' *assume* that (scheduling) priority while acting on its
>> behalf?  Magically, the priority of the activities being performed to
>> achieve your (task's) goal have changed -- just because some other
>> agency is performing them!?
> 
> One can certainly design and implement such a priority-inheritance
> mechanism in a system, even a distributed system (though in the latter
> case one would have to define a system-wide priority scale). I know of
> two examples for non-distributed systems: priority inheritance for
> resources (https://en.wikipedia.org/wiki/Priority_inheritance) and
> priority inheritance occurring when one Ada task requests a service from
> another Ada task
> (http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-D-1.html).
> 
> Don't blame the priority concept for poor or deficient implementations
> of priorities.
> 
>> "Priority" (in scheduling) is just a sort of efficiency hack.
> 
> No, it is the basis for one important set of the mathematical methods
> for verifying real-time performance: schedulability analysis.
> 
>> It's a direct carry-forward of interrupt priorities:  those being
>> scheduling decisions MADE IN HARDWARE at the level of the interrupt
>> controller (which acknowledges the fact that two or more different
>> activities are likely to occur simultaneously and something has to make
>> a CHOICE among them as to which ONE to grant access to the CPU for this
>> ISR).
> 
> Yes, so? This is "scheduling", and it applies as well to HW as to SW. In
> fact, there have been HW implementations of SW task schedulers -- RTOS
> "accelerators".
> 
>> And, if you look at most hardware systems, the activities mapped onto
>> individual IRQ "levels"/priorities are defined solely by the hardware
>> (chip) manufacturer.  The user/implementor has very little option how
>> to rearrange the relative priorities/levels AS IMPLEMENTED IN THE
>> HARDWARE; you can't arbitrarily decide that the priority levels should
>> be:
>>     UART_RxReady UART_TxReady ParityError PowerFail ReceiverOverrun
>>     NetworkPacketAvailable BREAK detected
>> vs:
>>     NetworkPacketAvailable BREAK detected UART_TxReady ParityError
>>     PowerFail UART_RxReady ReceiverOverrun
> 
> The SPARC processors I am familiar with do allow the application to
> configure the priorities of interrupts, to some extent.
> 
> Before microcontrollers and systems-on-chip, in the minicomputer era,
> many systems allowed application-specific interrupt priorities, because
> the priority of a peripheral interface was defined by the number of the
> slot into which the interface board was plugged.
> 
> The interrupt systems of CPU cores usually number the external interrupt
> lines and use the number as the priority. When the CPU core is embedded
> in an SoC or a microcontroller, the system designer assigns interrupt
> lines to on-chip peripherals, often with some specific type of
> application in mind, such as an auto engine controller. In this sense,
> interrupt priorities can still be application-specific.
> 
> Again, don't blame the priority concept for poor or deficient
> implementations of priorities.
> 
>> If you've ever had to "jigger" a priority, you should be asking,
>> "why did I *have* to do this?
> 
> So don't "jigger" them. Use a systematic, mathematically proven priority
> assignment principle supporting a schedulability analysis method.

You know, I've had nearly this same conversation with him (you're giving 
more detail, though).  About a month ago.  It didn't stick.  He's either 
very obtuse, or he's enjoying himself.

-- 

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

I'm looking for work -- see my website!

[toc] | [prev] | [next] | [standalone]


#24473

FromDimiter_Popoff <dp@tgi-sci.com>
Date2016-06-30 04:14 +0300
Message-ID<nl1rqg$cbg$1@dont-email.me>
In reply to#24446
On 29.6.2016 г. 19:36, Les Cargill wrote:
> Dimiter_Popoff wrote:
>> On 28.6.2016 г. 17:40, Tim Wescott wrote:
>>> On Tue, 28 Jun 2016 06:20:43 +0300, Dimiter_Popoff wrote:
>>>
>>>> On 28.6.2016 г. 05:54, Simon Clubley wrote:
>>>>>
>>>>   > .....
>>>>> I still think that's a polling loop because you are reaching out to
>>>>> the
>>>>> sensor and asking it for it's current value.
>>>>
>>>> "Polling" in programming means "as opposed to interrupt handling".
>>>> How is this opposed to "interrupt handling".
>>>>
>>>> What you suggest to be polling is simply a loop of calls to
>>>> subroutines.
>>>> A "call loop" is what describes it - although it does not matter a lot
>>>> what word is used as long as it is not an already widely accepted one
>>>> like "polling" which you want to redefine. Nothing wrong with that of
>>>> course - as long as you don't have to communicate with other people
>>>> using your redefined term.
>>>>
>>>> So much talk about so little :-). Although Tim's topic idea worked,
>>>> produced quite a discussion.
>>>
>>> Well, I was hoping for a name of a design pattern, and I'm still not
>>> happy about my choices.  So from that perspective it's a wash.
>>>
>>> "Super loop" seems closest, but it seems to more capture the notion of
>>> _always_ executing A, B, C, rather than executing only those bits that
>>> are ready.
>>>
>>
>> I encounter the "super loop" term for the first time here, but why not.
>> Although I see nothing "super" about it, to me this is still an endless
>> loop of calls to subroutines either of which may opt to do something
>> or to just return if it has nothing to do.
>> But like I said earlier I have almost never used this approach, it
>> smells of oversimplifying - thus costing more than a decent scheduler
>> does. Implement loops, state machines etc. as you like within tasks
>> but having a true - preemptive allowing cooperative operation- scheduler
>> costs very little in both machine resources and effort to put together
>> so I see no point in trying to avoid it.
>>
>
> Other than for ISRs, you really don't *need* preemption.
 > ...

I tend to agree with that - excepting the case of a larger system with
a user running this and that on it (in fact you still don't "need" it
there but it can be very useful, like saving you a reboot sometimes
by allowing you to kill the hogger etc.).

Like I said in another post here yesterday:

 > Of course, if you've got a bunch of fast tasks and even one slow one
 > (reciting the Gettysburg address to a human, for instance) then a
 > preemptive scheduler gets very attractive.
 >

I see the preemptive feature mostly as a backup plan, basically if the
reciter is say reciting through an UART at 9600 bps the output driver
would be exiting the task cooperatively long before being preempted
(say after filling an output FIFO of some 256 bytes or something).
But if the system is dynamic - e.g. a fullblown OS with a user in
front of it doing this and that - then preemption may well have to
kick in.

Dimiter


[toc] | [prev] | [next] | [standalone]


#24488

FromLes Cargill <lcargill99@comcast.com>
Date2016-06-30 17:07 -0500
Message-ID<nl450b$hf$1@dont-email.me>
In reply to#24473
Dimiter_Popoff wrote:
> On 29.6.2016 г. 19:36, Les Cargill wrote:
>> Dimiter_Popoff wrote:
>>> On 28.6.2016 г. 17:40, Tim Wescott wrote:
>>>> On Tue, 28 Jun 2016 06:20:43 +0300, Dimiter_Popoff wrote:
>>>>
>>>>> On 28.6.2016 г. 05:54, Simon Clubley wrote:
>>>>>>
>>>>>   > .....
>>>>>> I still think that's a polling loop because you are reaching out to
>>>>>> the
>>>>>> sensor and asking it for it's current value.
>>>>>
>>>>> "Polling" in programming means "as opposed to interrupt handling".
>>>>> How is this opposed to "interrupt handling".
>>>>>
>>>>> What you suggest to be polling is simply a loop of calls to
>>>>> subroutines.
>>>>> A "call loop" is what describes it - although it does not matter a lot
>>>>> what word is used as long as it is not an already widely accepted one
>>>>> like "polling" which you want to redefine. Nothing wrong with that of
>>>>> course - as long as you don't have to communicate with other people
>>>>> using your redefined term.
>>>>>
>>>>> So much talk about so little :-). Although Tim's topic idea worked,
>>>>> produced quite a discussion.
>>>>
>>>> Well, I was hoping for a name of a design pattern, and I'm still not
>>>> happy about my choices.  So from that perspective it's a wash.
>>>>
>>>> "Super loop" seems closest, but it seems to more capture the notion of
>>>> _always_ executing A, B, C, rather than executing only those bits that
>>>> are ready.
>>>>
>>>
>>> I encounter the "super loop" term for the first time here, but why not.
>>> Although I see nothing "super" about it, to me this is still an endless
>>> loop of calls to subroutines either of which may opt to do something
>>> or to just return if it has nothing to do.
>>> But like I said earlier I have almost never used this approach, it
>>> smells of oversimplifying - thus costing more than a decent scheduler
>>> does. Implement loops, state machines etc. as you like within tasks
>>> but having a true - preemptive allowing cooperative operation- scheduler
>>> costs very little in both machine resources and effort to put together
>>> so I see no point in trying to avoid it.
>>>
>>
>> Other than for ISRs, you really don't *need* preemption.
>  > ...
>
> I tend to agree with that - excepting the case of a larger system with
> a user running this and that on it (in fact you still don't "need" it
> there but it can be very useful, like saving you a reboot sometimes
> by allowing you to kill the hogger etc.).
>


I've just had great luck not writing hoggers in the first place. 
Sometimes this puts you in the position of decomposing the problem
in funny ways.

> Like I said in another post here yesterday:
>
>  > Of course, if you've got a bunch of fast tasks and even one slow one
>  > (reciting the Gettysburg address to a human, for instance) then a
>  > preemptive scheduler gets very attractive.
>  >
>
> I see the preemptive feature mostly as a backup plan, basically if the
> reciter is say reciting through an UART at 9600 bps the output driver
> would be exiting the task cooperatively long before being preempted
> (say after filling an output FIFO of some 256 bytes or something).
> But if the system is dynamic - e.g. a fullblown OS with a user in
> front of it doing this and that - then preemption may well have to
> kick in.
>

Might be convenient, but I rather doubt it's fully necessary. It's more
necessary when you have to  support multiple users.

The Gettysburg address goes out one byte, packet or phenome at a time.


> Dimiter
>
>
>

-- 
Les Cargill

[toc] | [prev] | [next] | [standalone]


#24494

FromDimiter_Popoff <dp@tgi-sci.com>
Date2016-07-01 02:28 +0300
Message-ID<nl49ui$eei$1@dont-email.me>
In reply to#24488
On 01.7.2016 г. 01:07, Les Cargill wrote:
> Dimiter_Popoff wrote:
>> On 29.6.2016 г. 19:36, Les Cargill wrote:
>>> Dimiter_Popoff wrote:
>>>> On 28.6.2016 г. 17:40, Tim Wescott wrote:
>>>>> On Tue, 28 Jun 2016 06:20:43 +0300, Dimiter_Popoff wrote:
>>>>>
>>>>>> On 28.6.2016 г. 05:54, Simon Clubley wrote:
>>>>>>>
>>>>>>   > .....
>>>>>>> I still think that's a polling loop because you are reaching out to
>>>>>>> the
>>>>>>> sensor and asking it for it's current value.
>>>>>>
>>>>>> "Polling" in programming means "as opposed to interrupt handling".
>>>>>> How is this opposed to "interrupt handling".
>>>>>>
>>>>>> What you suggest to be polling is simply a loop of calls to
>>>>>> subroutines.
>>>>>> A "call loop" is what describes it - although it does not matter a
>>>>>> lot
>>>>>> what word is used as long as it is not an already widely accepted one
>>>>>> like "polling" which you want to redefine. Nothing wrong with that of
>>>>>> course - as long as you don't have to communicate with other people
>>>>>> using your redefined term.
>>>>>>
>>>>>> So much talk about so little :-). Although Tim's topic idea worked,
>>>>>> produced quite a discussion.
>>>>>
>>>>> Well, I was hoping for a name of a design pattern, and I'm still not
>>>>> happy about my choices.  So from that perspective it's a wash.
>>>>>
>>>>> "Super loop" seems closest, but it seems to more capture the notion of
>>>>> _always_ executing A, B, C, rather than executing only those bits that
>>>>> are ready.
>>>>>
>>>>
>>>> I encounter the "super loop" term for the first time here, but why not.
>>>> Although I see nothing "super" about it, to me this is still an endless
>>>> loop of calls to subroutines either of which may opt to do something
>>>> or to just return if it has nothing to do.
>>>> But like I said earlier I have almost never used this approach, it
>>>> smells of oversimplifying - thus costing more than a decent scheduler
>>>> does. Implement loops, state machines etc. as you like within tasks
>>>> but having a true - preemptive allowing cooperative operation-
>>>> scheduler
>>>> costs very little in both machine resources and effort to put together
>>>> so I see no point in trying to avoid it.
>>>>
>>>
>>> Other than for ISRs, you really don't *need* preemption.
>>  > ...
>>
>> I tend to agree with that - excepting the case of a larger system with
>> a user running this and that on it (in fact you still don't "need" it
>> there but it can be very useful, like saving you a reboot sometimes
>> by allowing you to kill the hogger etc.).
>>
>
>
> I've just had great luck not writing hoggers in the first place.
> Sometimes this puts you in the position of decomposing the problem
> in funny ways.

Well this is not down to luck of course. I have not written any hoggers
either - except willingly, like the "hog" command for DPS I mentioned
earlier. Does a "bra *", sometimes I use it to see how this or that
behaves under severe system load.

Dimiter

[toc] | [prev] | [next] | [standalone]


#24415

FromDon Y <blockedofcourse@foo.invalid>
Date2016-06-28 12:02 -0700
Message-ID<nkuhki$pdu$1@dont-email.me>
In reply to#24402
On 6/27/2016 8:20 PM, Dimiter_Popoff wrote:
> On 28.6.2016 г. 05:54, Simon Clubley wrote:
>>
>  > .....
>> I still think that's a polling loop
>> because you are reaching out to the sensor and asking it for it's
>> current value.
>
> "Polling" in programming means "as opposed to interrupt handling".

I see "polling" as different from "event driven".  I *don't* see
event driven as requiring an interrupt (foreground) system!

I.e., why can't an "event" be totally synthetic:  10,000 iterations
of the "big loop"?  (before folks *dedicated* timer hardware to
implementations, you could still "write code"  :> )

Or, why can't an "event" be created by POLLING something?  A piece
of hardware *or* the results of some other "task"?

E.g., the "line frequency clock" I described elsewhere just *looks*
to see if a "zero crossing" has been detected on the AC mains
"since the last time I looked" (the time between "peeks" being
highly variable as it depends on how long it took to "go around
the loop" on this most recent iteration.

This "event" feeds an algorithm that effectively says:
    if (LFC_event) {
        signal_power_available()
    } else {
        missed_events++
        if (missed_events > THRESHOLD) {
            signal_power_fail()
        }
    }

[though it does this by way of a small state machine instead of
the spaghetti code above -- you don't want to "signal" power as
being available (or failed) if it already has been signaled as
such; that generates superfluous "conditions" instead of "events"]

> How is this opposed to "interrupt handling".
>
> What you suggest to be polling is simply a loop of calls to subroutines.
> A "call loop" is what describes it - although it does not matter a lot
> what word is used as long as it is not an already widely accepted one
> like "polling" which you want to redefine. Nothing wrong with that
> of course - as long as you don't have to communicate with
> other people using your redefined term.

IME, most people have their own private lexicons -- yet seem to think
theirs is "universally accepted" and/or "correct".

This is why I spend so much time writing "tutorials":
    "Hey, believe what you want.  But, *these* are the definitions
    that *I* use and this is why they make sense..."

> So much talk about so little :-). Although Tim's topic idea worked,
> produced quite a discussion.

[toc] | [prev] | [next] | [standalone]


#24420

FromHans-Bernhard Bröker <HBBroeker@t-online.de>
Date2016-06-28 23:19 +0200
Message-ID<dtg80fF7e5aU1@mid.dfncis.de>
In reply to#24415
Am 28.06.2016 um 21:02 schrieb Don Y:

> I see "polling" as different from "event driven".  I *don't* see
> event driven as requiring an interrupt (foreground) system!
>
> I.e., why can't an "event" be totally synthetic:  10,000 iterations
> of the "big loop"?  (before folks *dedicated* timer hardware to
> implementations, you could still "write code"  :> )

IMHO: because that would do violence to the language.  Events are things 
that just happen whenever they will, often without anyone having asked 
for them.  "Polling" is when somebody goes around asking people 
more-or-less silly questions.  That's what these things mean in 
non-technical speak, and it's generally best to stay close to those 
original meaning when we tech people appropriate them for our own use.

So the the difference between polling and interrupt-/event-driven 
operation is one of direction of activity.  It's the difference between 
pulling and pushing data from one place to an other.  One is where the 
door bell rings, the other is where you go look if there's mail in the box.

> Or, why can't an "event" be created by POLLING something?

It can be created by it, but it cannot _be_ it.

> E.g., the "line frequency clock" I described elsewhere just *looks*
> to see if a "zero crossing" has been detected on the AC mains

Actually no, that's not the event. The event was when the mains _did_ 
cross the line, not when you got around to looking if it had.

Whether that's event-driven or polled depends on _how_ you acquire the 
information that line is being crossed.  If you just look if the sign 
has changed, that's polling.  If you have hardware that fires some 
interrupt the very instant the line is crossed, that's event-driven.

The distinction is much less global than one might think, though: pnce 
the information has been handed over to software, the nature of its 
handling can change at any time (and repeatedly):

* You get an interrupt and just set a flag (or increase some counter)? 
That's an event turned to input for later polling.

* You noticed some condition turned true and call a function?  That's 
polled information being handled in an event-driven fashion.

[toc] | [prev] | [next] | [standalone]


#24414

FromDon Y <blockedofcourse@foo.invalid>
Date2016-06-28 11:51 -0700
Message-ID<nkugvq$mv4$1@dont-email.me>
In reply to#24400
On 6/27/2016 7:54 PM, Simon Clubley wrote:
> On 2016-06-27, Don Y <blockedofcourse@foo.invalid> wrote:
>>
>> The example:
>>      while (FOREVER) {
>>          V=readADC();
>>          writeDAC(V);
>>      }
>> you termed as "polling" -- despite the fact that there are no
>> visible conditionals.  (I don't consider the hardwired while()
>> to be a conditional -- it could be implemented with a goto.)
>>
>
> It is an interesting example. I still think that's a polling loop
> because you are reaching out to the sensor and asking it for it's
> current value.
>
> It's possible to have polling loops in which there is no conditional
> logic, but instead a pure mathematical transformation of an input
> to an output is performed. While there's no obvious maths going on
> in the above loop, you are still driving a second device based on
> the current value of the first device.

OK.  Here's pseudo-code for something I wrote many years ago to
"crack" Moore machines:

main()
    init()
    while (not_done) {
       state = get_current_state()
       stimulus = get_stimulus(state)
       put_stimulus(stimulus)
       update_display()
    }
}

I.e., this is indistinguishable from just "a looping algorithm".

get_current_state() "reaches out to the sensor" -- in this case, the
hardware implementing the FSM -- "and asks it for it's current value".

For some devices, this is just a memory/IO "read".  For others,
it might require massaging some hardware to extract the contents
of a "buried" state register, etc. (e.g. jtag interface).

[Likewise, put_stimulus() may be a simple "write" or a lengthy
"process (jtag) to introduce the chosen stimulus to the FSM]

Of course, get_stimulus() is the meat-and-potatoes of the algorithm...

Now, imagine I make the "FSM interfaces" interface to a *model* of
a FSM!  There's no IO involved.  No "sensors".  Just "data" driven
by an "isolated" algorithm that is pretending to be a piece of
hardware.

Is this still "polling"?  Or, something else -- because it is not interfacing
with "sensors"?  Even sensors who can be accessed unconditionally in the
same way that the outputs of a simulator could?

I.e., I could rewrite the Fibonacci example as a task interfacing to
a "Fibonacci simulator".  *Or*, a hardware device that was a "Fibonacci
generator"!  It's the same application -- that can be implemented
with virtually identical code (see my FSM example, above).  Yet,
you arbitrarily call it different things?

>> So far, your distinguishing criteria is "if interrupts are used,
>> then interrupt driven; else polling (even if no conditional logic
>> involved)"  ??
>
> To me, it's more like if you have to reach out to the sensors and ask
> them what their current status is, then it's polling. If you don't do
> anything until the sensor tells you via some mechanism that there's
> been a change in the sensor then to me it's an interrupt architecture.

What if the "some mechanism" doesn't actually tell you that there has
been a change?  Merely that "its time for you to look at it again"?

What if that mechanism is unrelated to any particular hardware (i.e.,
NOT sourced by an interrupt but, rather, 10,000 iterations around
the main loop?  (i.e., this activity has a relative weight of
1:10,000 while some other activity might have a relative weight of
1:5,000 or 1:1,000,000)

[toc] | [prev] | [next] | [standalone]


#24496

FromSimon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP>
Date2016-07-01 06:54 +0000
Message-ID<nl542h$c6t$1@dont-email.me>
In reply to#24414
On 2016-06-28, Don Y <blockedofcourse@foo.invalid> wrote:
>
> Now, imagine I make the "FSM interfaces" interface to a *model* of
> a FSM!  There's no IO involved.  No "sensors".  Just "data" driven
> by an "isolated" algorithm that is pretending to be a piece of
> hardware.
>
> Is this still "polling"?  Or, something else -- because it is not interfacing
> with "sensors"?  Even sensors who can be accessed unconditionally in the
> same way that the outputs of a simulator could?
>
> I.e., I could rewrite the Fibonacci example as a task interfacing to
> a "Fibonacci simulator".  *Or*, a hardware device that was a "Fibonacci
> generator"!  It's the same application -- that can be implemented
> with virtually identical code (see my FSM example, above).  Yet,
> you arbitrarily call it different things?
>

I'd say that's just a normal compute bound application.

The difference between your examples and what started this thread is
that the main loop in Tim's examples are about responding to external
hardware events whereas yours are purely internal software constructs.

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world

[toc] | [prev] | [next] | [standalone]


#24354

FromDimiter_Popoff <dp@tgi-sci.com>
Date2016-06-25 21:08 +0300
Message-ID<nkmhbe$60o$1@dont-email.me>
In reply to#24352
On 25.6.2016 г. 19:41, Don Y wrote:
> On 6/25/2016 8:27 AM, Simon Clubley wrote:
>> On 2016-06-24, Paul Rubin <no.email@nospam.invalid> wrote:
>>> Tim Wescott <seemywebsite@myfooter.really> writes:
>>>> So, this is the third time in a month or so that I've needed to tell
>>>> someone "use a task loop" -- but I'm not sure if I can say "just Google
>>>> it".
>>>
>>> I'd call that a polling loop, since it polls each task to see if it's
>>> ready.  But I don't know if that's a standard term.
>>
>> Until I read your reply, this was _exactly_ what I was going to say.
>>
>> It _is_ a polling loop (or polling architecture if you want to
>> distinguish it from an interrupt architecture.)
>
> No.  Why does any "polling" have to occur?  Why can't every task be
> treated as active/ready?  Why can't it coexist with an active foreground?

Hi Don,
[no, no icicles here any longer 30+C actually, very nice
- for a change... ]

may be "calling" rather than polling :-).

I did it just once for a project out of curiousity - to see how much
effort it would save me by not having a decent scheduler.
It saved nothing at best, probably it cost me more work.

On another post of yours re overhead of a "calling loop" vs. a true
scheduler, I would say this is not a good deal at all.

Even a scheduler as complex as the one DPS has - it handles priorities,
provides fairness (so no one can hog the system), allows cooperative
task exits (is done all the time actually) while forcing tasks out
after some predefined time, gives a path to interrupts to kick the
current task out and strongly suggest the one the interrupt wants
to execute now etc. etc. is responsible for < 1% of the total
overhead. (Under system load that is, if none of the tasks has
anything to do and keeps quitting this is what will happen
all the time, obviously).
And having a good scheduler underneath makes you just forget about
scheduling, I can't remember when I last had to think about it.

Dimiter

------------------------------------------------------
Dimiter Popoff, TGI             http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/

[toc] | [prev] | [next] | [standalone]


#24364

FromDon Y <blockedofcourse@foo.invalid>
Date2016-06-25 15:24 -0700
Message-ID<nkn09p$sj9$1@dont-email.me>
In reply to#24354
Hi Dimiter,

On 6/25/2016 11:08 AM, Dimiter_Popoff wrote:

> [no, no icicles here any longer 30+C actually, very nice
> - for a change... ]

Well, to be honest, I kinda was figuring they'd be melted, by now!  :>

> may be "calling" rather than polling :-).
>
> I did it just once for a project out of curiousity - to see how much
> effort it would save me by not having a decent scheduler.
> It saved nothing at best, probably it cost me more work.

Removing the scheduler, IME, only makes sense on really small
designs.

But, the point is, you don't have to give up multitasking just
because you've done away with the scheduler!  IMO, the biggest
technological productivity enhancement is the decomposition
that multitasking affords.  Its easier to get the code
*right* as well as getting it *done*.

> On another post of yours re overhead of a "calling loop" vs. a true
> scheduler, I would say this is not a good deal at all.

See above.  I can hack together a really "rich" development
environment on a really *tiny* MCU by resorting to this sort
of trickery.  When you're dealing with a few *hundred* bytes
of RAM, more "formal" methods just aren't practical.  But,
resorting to ad hoc spaghetti coding for anything of substance
(little RAM doesn't mean little ROM!) is a Rx for disaster!

> Even a scheduler as complex as the one DPS has - it handles priorities,
> provides fairness (so no one can hog the system), allows cooperative
> task exits (is done all the time actually) while forcing tasks out
> after some predefined time, gives a path to interrupts to kick the
> current task out and strongly suggest the one the interrupt wants
> to execute now etc. etc. is responsible for < 1% of the total
> overhead. (Under system load that is, if none of the tasks has
> anything to do and keeps quitting this is what will happen
> all the time, obviously).
> And having a good scheduler underneath makes you just forget about
> scheduling, I can't remember when I last had to think about it.

My schedulers have become increasingly complex, with experience.
I want the "system" to do A LOT for me -- so I can concentrate
on solving a problem at hand (instead of managing processor
resources).  I want per process protection domains, kernel
mediated IPC, seemless RPC, the ability to detect when a
deadline has been missed and "handle" that event in a timely
fashion, decide which tasks can perform which actions on which
resources, etc.  Let the machine deal with all this bookkeeping
so I can concentrate on addressing the problem...

Currently, I have a "per core" scheduler that handles scheduling
resources for a "single virtual CPU".  As I'm now seeing that I can
buy multicore processors for what I've budgeted for single cores
in the past, I'm now adding scheduling for the multiple cores
on a particular physical processor.  And, beyond that, a "workload
scheduler" that decides which processors (nodes) will host which
jobs (I allow processes to physically migrate at run time to exploit
available "remote" hardware as the *system* load increases).

Of course, there's a lot less "science" behind these last two issues
as it's only recently been practical to distribute workloads over
multiple closely (and loosely) coupled processors.  Especially
when there are nontrivial communication costs involved in "leaving
the local node".

OTOH, your algorithms don't have to be "ideal" when MIPS are so cheap!

[Off to bury a friend...  :< ]

[toc] | [prev] | [next] | [standalone]


#24355

Fromupsidedown@downunder.com
Date2016-06-25 21:52 +0300
Message-ID<b1ktmb95c2ecb68spkcg0brfgt3kufcmdp@4ax.com>
In reply to#24352
On Sat, 25 Jun 2016 09:41:46 -0700, Don Y
<blockedofcourse@foo.invalid> wrote:

>On 6/25/2016 8:27 AM, Simon Clubley wrote:
>> On 2016-06-24, Paul Rubin <no.email@nospam.invalid> wrote:
>>> Tim Wescott <seemywebsite@myfooter.really> writes:
>>>> So, this is the third time in a month or so that I've needed to tell
>>>> someone "use a task loop" -- but I'm not sure if I can say "just Google
>>>> it".
>>>
>>> I'd call that a polling loop, since it polls each task to see if it's
>>> ready.  But I don't know if that's a standard term.
>>
>> Until I read your reply, this was _exactly_ what I was going to say.
>>
>> It _is_ a polling loop (or polling architecture if you want to
>> distinguish it from an interrupt architecture.)
>
>No.  Why does any "polling" have to occur?  Why can't every task be
>treated as active/ready?  Why can't it coexist with an active foreground?
>
>How do you address task_N's whose ready conditions can't be simply
>externalized as "task_N_ready"?  (Or, are you ONLY addressing implementations
>where this is the case -- ignoring any other sort of implementation that
>can ALSO exploit a "big loop"?)

In the 1970's this was implemented with the event flag register
concept.

On a 16 bit machine a global 16 bit event flag register was used and
each task had a wait for event flag mask.  The scheduler performed an
AND operation between the global event flag register and the task wait
mask. If the result was non-zero, the task executed. Very light weight
scheduling if the number if the event flags fit into one machine word
and not horribly inefficient, even if you had to test a few machine
words :-)

This concept could be used on a task loop as well.
 

[toc] | [prev] | [next] | [standalone]


#24372

FromDon Y <blockedofcourse@foo.invalid>
Date2016-06-26 01:04 -0700
Message-ID<nko2af$joi$1@dont-email.me>
In reply to#24355
On 6/25/2016 11:52 AM, upsidedown@downunder.com wrote:
> On Sat, 25 Jun 2016 09:41:46 -0700, Don Y
> <blockedofcourse@foo.invalid> wrote:
>
>> On 6/25/2016 8:27 AM, Simon Clubley wrote:
>>> On 2016-06-24, Paul Rubin <no.email@nospam.invalid> wrote:
>>>> Tim Wescott <seemywebsite@myfooter.really> writes:
>>>>> So, this is the third time in a month or so that I've needed to tell
>>>>> someone "use a task loop" -- but I'm not sure if I can say "just Google
>>>>> it".
>>>>
>>>> I'd call that a polling loop, since it polls each task to see if it's
>>>> ready.  But I don't know if that's a standard term.
>>>
>>> Until I read your reply, this was _exactly_ what I was going to say.
>>>
>>> It _is_ a polling loop (or polling architecture if you want to
>>> distinguish it from an interrupt architecture.)
>>
>> No.  Why does any "polling" have to occur?  Why can't every task be
>> treated as active/ready?  Why can't it coexist with an active foreground?
>>
>> How do you address task_N's whose ready conditions can't be simply
>> externalized as "task_N_ready"?  (Or, are you ONLY addressing implementations
>> where this is the case -- ignoring any other sort of implementation that
>> can ALSO exploit a "big loop"?)
>
> In the 1970's this was implemented with the event flag register
> concept.
>
> On a 16 bit machine a global 16 bit event flag register was used and
> each task had a wait for event flag mask.  The scheduler performed an
> AND operation between the global event flag register and the task wait
> mask. If the result was non-zero, the task executed. Very light weight
> scheduling if the number if the event flags fit into one machine word
> and not horribly inefficient, even if you had to test a few machine
> words :-)
>
> This concept could be used on a task loop as well.

There are some 8051 "OS's" that use this approach (very limited
number of tasks)

It means <something> has to actively detect the various conditions
that might "make ready" a particular task.  And, to potentially do
it every time that set of conditions proves to be true.

If you are interfacing something in the foreground (scarce time
resources) to something in the background (e.g., "characters
available in the UART receive FIFO"), then that's another
action that must be taken in that foreground.

Many MTOS's have support for events (some latching, others
self-clearing).  It's a relatively cheap way of passing (very
little) information.

E.g., "I have detected a 60Hz mains zero crossing".  So, a
background task can poll this -- or, in a preemptive scheduler,
be automatically unblocked when it occurs -- and know that
the "event" happened.

However, there is limited utility.

E.g., a UART might want to signal that it has some data in the
receive ISR's FIFO.  Or, that the receive FIFO has been OVERRUN
(potentially very different reactions to these events).  Or,
that the transmit ISR has emptied its FIFO and is preparing to
shut down the transmitter.  Or, that a BREAK has been detected
(unless you can encode them in-line AND they have no associated
immediacy)

OTOH, if a task can sit and watch for whatever it considers
important (assuming you aren't using an OS), then it can
implement whatever tests *it* deems appropriate -- now, and
a potentially different set, later.

E.g., I discussed one of my early barcode readers in another
post.  The ISR buffers "transition times" (edges) in a FIFO.
The background extracts these.  Should the background handler
lock the FIFO (disable interrupts) to extract *one* edge?
Or, should it possibly wait for 2 (white-to-black at the leading
ede of a "bar" followed by white-to-black at the end of the "bar")?
I.e., processing just a bar or just a space isn't of any help
as a "character code" consists of a multiple of such bars/spaces.

If the FIFO is *that* empty, maybe we shouldn't bother trying to
extract anything, yet?  Let some other task use the time that
we would otherwise spend doing that!  (and, avoid interfering
with the ISR itself -- by leaving interrupts enabled!)

You can usually arrange to leave some data in a "convenient" form
so that it can easily be tested and acted upon.  So, a waiting
task can simply load the data, make a test and either return to
sleep (relinquish the CPU) *or* wake up and act on it.  The
"testing" is done in the "background" -- where time isn't as
scarce as it is in the foreground!

And, what do you do in cases where the/all tasks are *always*
ready (in a global sense)?  I.e., I might be waiting for an
incoming character from a UART, now -- and a timer to expire
later -- followed by space in the same UART's transmit FIFO
some time after that!  Do these have to be three different
tasks because they rely on three different "readiness" criteria?
Do you have to keep the tasks in lock sync with the "producers"
that are detecting the conditions that are assigned to each
flag *now*?

[toc] | [prev] | [next] | [standalone]


#24374

Fromupsidedown@downunder.com
Date2016-06-26 13:46 +0300
Message-ID<krbvmb5sinobt4ahlmvqm4on7ent26ome5@4ax.com>
In reply to#24372
On Sun, 26 Jun 2016 01:04:42 -0700, Don Y
<blockedofcourse@foo.invalid> wrote:

>On 6/25/2016 11:52 AM, upsidedown@downunder.com wrote:
>> On Sat, 25 Jun 2016 09:41:46 -0700, Don Y
>> <blockedofcourse@foo.invalid> wrote:
>>
>>> On 6/25/2016 8:27 AM, Simon Clubley wrote:
>>>> On 2016-06-24, Paul Rubin <no.email@nospam.invalid> wrote:
>>>>> Tim Wescott <seemywebsite@myfooter.really> writes:
>>>>>> So, this is the third time in a month or so that I've needed to tell
>>>>>> someone "use a task loop" -- but I'm not sure if I can say "just Google
>>>>>> it".
>>>>>
>>>>> I'd call that a polling loop, since it polls each task to see if it's
>>>>> ready.  But I don't know if that's a standard term.
>>>>
>>>> Until I read your reply, this was _exactly_ what I was going to say.
>>>>
>>>> It _is_ a polling loop (or polling architecture if you want to
>>>> distinguish it from an interrupt architecture.)
>>>
>>> No.  Why does any "polling" have to occur?  Why can't every task be
>>> treated as active/ready?  Why can't it coexist with an active foreground?
>>>
>>> How do you address task_N's whose ready conditions can't be simply
>>> externalized as "task_N_ready"?  (Or, are you ONLY addressing implementations
>>> where this is the case -- ignoring any other sort of implementation that
>>> can ALSO exploit a "big loop"?)
>>
>> In the 1970's this was implemented with the event flag register
>> concept.
>>
>> On a 16 bit machine a global 16 bit event flag register was used and
>> each task had a wait for event flag mask.  The scheduler performed an
>> AND operation between the global event flag register and the task wait
>> mask. If the result was non-zero, the task executed. Very light weight
>> scheduling if the number if the event flags fit into one machine word
>> and not horribly inefficient, even if you had to test a few machine
>> words :-)
>>
>> This concept could be used on a task loop as well.
>
>There are some 8051 "OS's" that use this approach (very limited
>number of tasks)

On RSX-11M (PDP11) had a 16 bit global event flag register. On
RSX-11M+ had 16 bit group global event flag registers for each (up to
256) user groups.
 

>It means <something> has to actively detect the various conditions
>that might "make ready" a particular task.  And, to potentially do
>it every time that set of conditions proves to be true.

The process that generates an event will set the appropriate event
flag register bit. No problem.

>If you are interfacing something in the foreground (scarce time
>resources) to something in the background (e.g., "characters
>available in the UART receive FIFO"), then that's another
>action that must be taken in that foreground.
>
>Many MTOS's have support for events (some latching, others
>self-clearing).  It's a relatively cheap way of passing (very
>little) information.
>
>E.g., "I have detected a 60Hz mains zero crossing".  So, a
>background task can poll this -- or, in a preemptive scheduler,
>be automatically unblocked when it occurs -- and know that
>the "event" happened.
>
>However, there is limited utility.
>
>E.g., a UART might want to signal that it has some data in the
>receive ISR's FIFO.  Or, that the receive FIFO has been OVERRUN
>(potentially very different reactions to these events).  Or,
>that the transmit ISR has emptied its FIFO and is preparing to
>shut down the transmitter.  Or, that a BREAK has been detected
>(unless you can encode them in-line AND they have no associated
>immediacy)
>
>OTOH, if a task can sit and watch for whatever it considers
>important (assuming you aren't using an OS), then it can
>implement whatever tests *it* deems appropriate -- now, and
>a potentially different set, later.
>
>E.g., I discussed one of my early barcode readers in another
>post.  The ISR buffers "transition times" (edges) in a FIFO.
>The background extracts these.  Should the background handler
>lock the FIFO (disable interrupts) to extract *one* edge?
>Or, should it possibly wait for 2 (white-to-black at the leading
>ede of a "bar" followed by white-to-black at the end of the "bar")?
>I.e., processing just a bar or just a space isn't of any help
>as a "character code" consists of a multiple of such bars/spaces.
>
>If the FIFO is *that* empty, maybe we shouldn't bother trying to
>extract anything, yet?  Let some other task use the time that
>we would otherwise spend doing that!  (and, avoid interfering
>with the ISR itself -- by leaving interrupts enabled!)
>
>You can usually arrange to leave some data in a "convenient" form
>so that it can easily be tested and acted upon.  So, a waiting
>task can simply load the data, make a test and either return to
>sleep (relinquish the CPU) *or* wake up and act on it.  The
>"testing" is done in the "background" -- where time isn't as
>scarce as it is in the foreground!
>
>And, what do you do in cases where the/all tasks are *always*
>ready (in a global sense)?  I.e., I might be waiting for an
>incoming character from a UART, now -- and a timer to expire
>later -- followed by space in the same UART's transmit FIFO
>some time after that!  Do these have to be three different
>tasks because they rely on three different "readiness" criteria?
>Do you have to keep the tasks in lock sync with the "producers"
>that are detecting the conditions that are assigned to each
>flag *now*?

On RSX-11 you posted an read/write QIO request and defined an event
flag (typically #5 for terminal I/O), the OS then set this event flag
when something happened on the serial line, such as received a
character, had a framing error etc. The task waiting for the event
flag then determined what was the cause of the recent flag setting.

[toc] | [prev] | [next] | [standalone]


#24375

FromDon Y <blockedofcourse@foo.invalid>
Date2016-06-26 05:11 -0700
Message-ID<nkogp9$vvc$1@dont-email.me>
In reply to#24374
On 6/26/2016 3:46 AM, upsidedown@downunder.com wrote:

>> It means <something> has to actively detect the various conditions
>> that might "make ready" a particular task.  And, to potentially do
>> it every time that set of conditions proves to be true.
>
> The process that generates an event will set the appropriate event
> flag register bit. No problem.

It means the signaling needs of one task have to be implemented by another.
If the signaled task decides it wants to respond to a different set
of conditions, then the signaling task has to be modified to
detect those, instead of the original set.

This can be a design-time change ("I'd rather only be notified of
Rx FIFO activity") *or* a run-time change ("NOW, I'd like to be notified
of *any* FIFO activity").

>> And, what do you do in cases where the/all tasks are *always*
>> ready (in a global sense)?  I.e., I might be waiting for an
>> incoming character from a UART, now -- and a timer to expire
>> later -- followed by space in the same UART's transmit FIFO
>> some time after that!  Do these have to be three different
>> tasks because they rely on three different "readiness" criteria?
>> Do you have to keep the tasks in lock sync with the "producers"
>> that are detecting the conditions that are assigned to each
>> flag *now*?
>
> On RSX-11 you posted an read/write QIO request and defined an event
> flag (typically #5 for terminal I/O), the OS then set this event flag
> when something happened on the serial line, such as received a
> character, had a framing error etc. The task waiting for the event
> flag then determined what was the cause of the recent flag setting.

So, the signaled task has to wake up to decide if it really
*wants* to be awakened.

[toc] | [prev] | [next] | [standalone]


#24376

Fromupsidedown@downunder.com
Date2016-06-26 15:35 +0300
Message-ID<1kivmbdvecnmtbaitr6qg0rmol0t520ejr@4ax.com>
In reply to#24375
On Sun, 26 Jun 2016 05:11:32 -0700, Don Y
<blockedofcourse@foo.invalid> wrote:

>> On RSX-11 you posted an read/write QIO request and defined an event
>> flag (typically #5 for terminal I/O), the OS then set this event flag
>> when something happened on the serial line, such as received a
>> character, had a framing error etc. The task waiting for the event
>> flag then determined what was the cause of the recent flag setting.
>
>So, the signaled task has to wake up to decide if it really
>*wants* to be awakened.

You must be trolling.

If I post a read/write channel, the expected result would be byte
received or byte sent.  However, if the result is different, such as
timeout, framing error, parity error etc. it is as important to
receive a notification of such events. It is much more convenient to
have a channel specific event flag than having to search for the
reason from a multiline serial card status registers.

[toc] | [prev] | [next] | [standalone]


Page 9 of 10 — ← Prev page 1 … 7 8 [9] 10  Next page →

Back to top | Article view | comp.arch.embedded


csiph-web