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


Groups > comp.lang.c > #92512 > unrolled thread

Default values in #define

Started by"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
First post2016-08-19 14:22 -0700
Last post2016-08-22 05:11 -0700
Articles 20 on this page of 355 — 30 participants

Back to article view | Back to comp.lang.c


Contents

  Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-19 14:22 -0700
    Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-20 09:36 +1200
      Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-19 22:48 +0100
        Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-19 14:56 -0700
        Re: Default values in #define Chad <cdalten@gmail.com> - 2016-08-22 07:56 -0700
          Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-22 17:09 +0200
            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 08:21 -0700
              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 08:47 -0700
                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 08:55 -0700
              Re: Default values in #define supercat@casperkitty.com - 2016-08-22 09:27 -0700
                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 09:41 -0700
                Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-22 20:19 +0100
                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 12:54 -0700
                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 09:14 +0200
                      Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 05:23 -0700
                        Re: Default values in #define mark.bluemel@gmail.com - 2016-08-23 05:42 -0700
                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 05:52 -0700
                            Re: Default values in #define mark.bluemel@gmail.com - 2016-08-23 06:01 -0700
                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:06 -0700
                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:01 -0700
                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 15:56 +0200
                                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:59 -0700
                                Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-23 10:42 -0700
                            Re: Default values in #define matt@godbolt.org - 2016-08-23 06:47 -0700
                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 15:57 +0200
                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 15:31 +0200
                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:43 -0700
                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 16:06 +0200
                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 07:15 -0700
                              Re: Default values in #define albert@cherry.spenarnc.xs4all.nl (Albert van der Horst) - 2016-12-04 13:26 +0100
                                Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-05 22:07 -0600
                                  Re: Default values in #define supercat@casperkitty.com - 2016-12-06 06:22 -0800
                                    Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-07 00:50 -0600
                                      Re: Default values in #define supercat@casperkitty.com - 2016-12-07 06:33 -0800
                                        Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-07 23:06 -0600
                                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-08 01:44 -0800
                                            Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-08 06:58 -0600
                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-10 08:16 -0800
                                              Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-11 02:47 -0600
                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 15:49 -0800
                                            Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 15:52 -0800
                                      Re: Default values in #define asetofsymbols@gmail.com - 2016-12-09 00:52 -0800
                                        Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-10 03:19 -0600
                                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-07 04:43 -0800
                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-08 14:18 +0100
                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-08 07:22 -0800
                                    Re: Default values in #define supercat@casperkitty.com - 2016-12-08 08:00 -0800
                                      Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-08 22:14 +0100
                                        Re: Default values in #define supercat@casperkitty.com - 2016-12-08 13:44 -0800
                                  Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 16:07 -0800
                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-09 17:00 -0800
                                      Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 17:46 -0800
                                        Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-10 08:37 -0800
                                          Re: Default values in #define supercat@casperkitty.com - 2016-12-10 09:42 -0800
                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-10 10:05 -0800
                                          Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-11 02:51 -0600
                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-11 04:40 -0800
                                              Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-11 23:06 -0600
                                                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-12 03:15 -0800
                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-12 16:12 +0100
                                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-12 07:33 -0800
                                                      Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-13 01:45 -0600
                                                    Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-12 16:49 +0000
                                                      Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-12 10:25 -0800
                                                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-13 10:50 +0100
                                                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 04:02 -0800
                                                            Re: Default values in #define BartC <bc@freeuk.com> - 2016-12-13 13:14 +0000
                                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 05:57 -0800
                                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-13 14:32 +0100
                                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 05:58 -0800
                                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 06:21 -0800
                                                                Re: Default values in #define BartC <bc@freeuk.com> - 2016-12-13 14:41 +0000
                                                                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 06:47 -0800
                                                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-13 16:24 +0100
                                                                      Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 07:30 -0800
                                                                      Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-14 14:12 -0600
                                                                        Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-14 12:21 -0800
                                                                          Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-14 15:02 -0600
                                                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-14 13:19 -0800
                                                              Petty and unprofessional (Was: Default values in #define) gazelle@shell.xmission.com (Kenny McCormack) - 2016-12-13 16:46 +0000
                                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 09:04 -0800
                                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-13 20:06 +0100
                                                                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 11:19 -0800
                                                                  Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-12-13 11:33 -0800
                                                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 11:44 -0800
                                                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-14 10:04 +0100
                                                              Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 14:37 -0800
                                                              Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-12-14 14:28 -0600
                                                            Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 14:23 -0800
                                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 16:10 -0800
                                                                Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 18:54 -0800
                                                                  Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 18:57 -0800
                                                                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-14 02:53 -0800
                                                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-14 05:59 -0800
                                                                      Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-14 12:03 -0800
                                                                      Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-14 12:22 -0800
                                                                        Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-14 17:09 -0800
                                                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-14 18:37 -0800
                                                      Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-13 05:25 -0800
                                                  Re: Default values in #define supercat@casperkitty.com - 2016-12-12 07:31 -0800
                                                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-12 07:35 -0800
                                                    Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-12-12 09:17 -0800
                                                      Re: Default values in #define supercat@casperkitty.com - 2016-12-12 11:03 -0800
                                                        Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-12-12 11:41 -0800
                                                          Re: Default values in #define supercat@casperkitty.com - 2016-12-12 12:31 -0800
                                                            Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-12-12 13:13 -0800
                                                        Re: Default values in #define BartC <bc@freeuk.com> - 2016-12-12 20:22 +0000
                                            Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-11 14:49 +0000
                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-11 07:10 -0800
                                                Re: Default values in #define luser droog <luser.droog@gmail.com> - 2016-12-11 07:21 -0800
                                                  Re: Default values in #define jameskuyper@verizon.net - 2016-12-11 10:33 -0800
                                                Re: Default values in #define Melzzzzz <mel@zzzzz.com> - 2016-12-11 16:22 +0100
                                              Re: Default values in #define luser droog <luser.droog@gmail.com> - 2016-12-11 07:16 -0800
                                            Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 13:54 -0800
                                              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 14:09 -0800
                                                Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-13 14:31 -0800
                                                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-13 16:11 -0800
                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:49 -0700
                          Re: Default values in #define Andrew Haley <andrew29@littlepinkcloud.invalid> - 2016-12-21 05:50 -0600
                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-12-21 13:10 +0100
                  Re: Default values in #define supercat@casperkitty.com - 2016-08-22 12:56 -0700
                    Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-22 21:11 +0100
                    Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-22 15:47 -0700
                      Re: Default values in #define supercat@casperkitty.com - 2016-08-23 11:54 -0700
                        Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-23 20:07 +0100
                          Re: Default values in #define supercat@casperkitty.com - 2016-08-23 14:30 -0700
                            Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-24 06:25 +0100
                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-24 10:34 +0200
                              Re: Default values in #define Richard Damon <Richard@Damon-Family.org> - 2016-08-24 08:50 -0400
                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-24 15:37 +0200
                                  Re: Default values in #define supercat@casperkitty.com - 2016-08-24 11:58 -0700
                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-25 01:27 +0200
                                      Re: Default values in #define supercat@casperkitty.com - 2016-08-24 22:28 -0700
                                        Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-24 23:38 -0700
                                          Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-25 10:44 +0200
                                          Re: Default values in #define supercat@casperkitty.com - 2016-08-25 07:29 -0700
                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-25 07:32 -0700
                                              Re: Default values in #define supercat@casperkitty.com - 2016-08-25 10:26 -0700
                                                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-25 11:11 -0700
                                                  Re: Default values in #define supercat@casperkitty.com - 2016-08-25 12:03 -0700
                                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:31 +0200
                                                Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-29 09:28 -0700
                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 22:51 +0200
                                                    Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-29 16:35 -0700
                                                      Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 01:44 +0200
                                                      Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-08-30 10:06 -0700
                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-30 10:41 -0700
                                                          Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 21:24 +0200
                                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 12:32 -0700
                                                              Re: Default values in #define Jean-Marc Bourguet <jm@bourguet.org> - 2016-08-30 22:30 +0200
                                                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-31 09:17 +0200
                                                          Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-08-31 22:46 -0700
                                                        Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-31 10:29 -0700
                                                          Re: Default values in #define supercat@casperkitty.com - 2016-08-31 10:12 -0700
                                                            Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-08-31 12:30 -0700
                                                              Re: Default values in #define supercat@casperkitty.com - 2016-08-31 11:32 -0700
                                                            Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-08-31 22:56 -0700
                                                              Re: Default values in #define supercat@casperkitty.com - 2016-09-01 08:17 -0700
                                                                Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 22:18 -0700
                                                          Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-08-31 22:34 -0700
                                                            Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-09-01 00:32 -0700
                                                              Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-02 05:19 -0700
                                                          Re: Default values in #define Jean-Marc Bourguet <jm@bourguet.org> - 2016-09-01 11:38 +0200
                                                            Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-09-01 10:03 -0700
                                                              Re: Default values in #define supercat@casperkitty.com - 2016-09-01 10:31 -0700
                                                                Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-09-01 12:50 -0700
                                                              Re: Default values in #define Jean-Marc Bourguet <jm@bourguet.org> - 2016-09-01 21:30 +0200
                                                              Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-02 05:37 -0700
                                                                Re: Default values in #define supercat@casperkitty.com - 2016-09-02 08:16 -0700
                                                                  Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 22:20 -0700
                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-09-06 07:32 -0700
                                                                      Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-11 06:54 -0700
                                                                Re: Default values in #define Keith Thompson <kst-u@mib.org> - 2016-09-02 08:40 -0700
                                                                  Re: Default values in #define supercat@casperkitty.com - 2016-09-02 10:16 -0700
                                                                  Re: Default values in #define Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 15:16 -0700
                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-25 08:28 -0700
                                              Re: Default values in #define supercat@casperkitty.com - 2016-08-25 10:14 -0700
                                                Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 00:54 -0700
                                                Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 01:00 -0700
                                                  Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-26 11:17 +0100
                                                    Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 04:08 -0700
                                                      Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-26 13:45 +0100
                                                        Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 06:09 -0700
                                                          Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-26 17:11 +0100
                                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 09:31 -0700
                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-26 12:48 -0400
                                                              Re: Default values in #define supercat@casperkitty.com - 2016-08-26 09:50 -0700
                                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:01 +0200
                                                                  Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-29 10:57 -0700
                                                                Re: Default values in #define Ike Naar <ike@iceland.freeshell.org> - 2016-08-31 06:09 +0000
                                                              Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-26 12:24 -0700
                                                                Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-26 17:27 -0700
                                                                  Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-26 17:39 -0700
                                                              Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-26 21:49 +0100
                                                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:51 +0200
                                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:46 +0200
                                                          Re: Default values in #define Richard Damon <Richard@Damon-Family.org> - 2016-08-26 17:37 -0400
                                                            Re: Default values in #define supercat@casperkitty.com - 2016-08-26 15:05 -0700
                                                              Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-27 10:25 +1200
                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-26 16:25 -0700
                                                                Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 18:12 -0700
                                                                  Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-27 13:47 +1200
                                                                    Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 19:32 -0700
                                                                      Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-26 22:54 -0400
                                                                        Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-26 21:11 -0700
                                                                          Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-27 18:25 +1200
                                                                          Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 09:11 -0400
                                                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-27 06:33 -0700
                                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 10:16 -0400
                                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-27 13:17 -0700
                                                                                  Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 16:26 -0400
                                                                            Re: Default values in #define supercat@casperkitty.com - 2016-08-27 13:10 -0700
                                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 16:35 -0400
                                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-29 09:28 -0700
                                                                                  Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-29 15:38 -0400
                                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-08-29 13:27 -0700
                                                                                      Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-29 16:42 -0400
                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-29 14:16 -0700
                                                                                          Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-29 17:24 -0400
                                                                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:21 +0200
                                                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-30 08:12 -0400
                                                                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 15:24 +0200
                                                                                                  Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-30 10:53 -0400
                                                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-08-30 10:34 -0700
                                                                                                      Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-30 14:44 -0400
                                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-30 12:48 -0700
                                                                                                          Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-30 17:19 -0400
                                                                                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-31 11:24 +0200
                                                                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-31 10:33 -0400
                                                                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-31 09:51 -0700
                                                                                                                  Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-31 22:46 -0400
                                                                                                      Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-30 16:26 -0700
                                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-09-03 17:31 -0700
                                                                                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 16:03 -0800
                                                                                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 21:36 +0200
                                                                                                      Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-30 17:30 -0400
                                                                                                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-31 12:39 +0200
                                                                                                          Re: Default values in #define already5chosen@yahoo.com - 2016-08-31 03:57 -0700
                                                                                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-31 15:34 +0200
                                                                                                              Re: Default values in #define already5chosen@yahoo.com - 2016-08-31 07:33 -0700
                                                                                                          Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-31 10:46 -0400
                                                                                                            Re: Default values in #define supercat@casperkitty.com - 2016-08-31 10:03 -0700
                                                                                                              Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-31 22:52 -0400
                                                                                                                Re: Default values in #define supercat@casperkitty.com - 2016-09-01 07:41 -0700
                                                                                                                  Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-01 14:58 -0400
                                                                                                      Re: Default values in #define already5chosen@yahoo.com - 2016-08-31 02:27 -0700
                                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-31 08:21 -0700
                                                                                                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-31 09:05 -0700
                                                                                                            Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-31 09:15 -0700
                                                                                                            Re: Default values in #define Rosario19 <Ros@invalid.invalid> - 2016-09-02 22:22 +0200
                                                                              Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-28 08:41 +1200
                                                                                Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 20:34 -0400
                                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-29 09:41 -0700
                                                                                  Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-30 08:07 +1200
                                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-08-29 14:08 -0700
                                                                                      Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-29 15:41 -0700
                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-29 16:30 -0700
                                                                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-29 17:14 -0700
                                                                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-29 17:20 -0700
                                                                                            Re: Default values in #define supercat@casperkitty.com - 2016-08-29 23:37 -0700
                                                                                              Re: Default values in #define already5chosen@yahoo.com - 2016-08-30 02:19 -0700
                                                                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:26 +0200
                                                                                                  Re: Default values in #define already5chosen@yahoo.com - 2016-08-30 04:40 -0700
                                                                                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:56 +0200
                                                                                                Re: Default values in #define albert@cherry.spenarnc.xs4all.nl (Albert van der Horst) - 2016-12-04 15:43 +0100
                                                                                      Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-30 19:34 +1200
                                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-30 00:51 -0700
                                                                                          Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-30 20:36 +1200
                                                                              Re: Default values in #define Robert Wessel <robertwessel2@yahoo.com> - 2016-08-31 00:39 -0500
                                                                        Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-26 21:40 -0700
                                                                          Re: Default values in #define Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-27 09:22 -0400
                                                                            Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-29 11:36 -0700
                                                                            Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-09 16:26 -0800
                                                                      Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-27 06:34 +0100
                                                                  Re: Default values in #define supercat@casperkitty.com - 2016-08-27 12:48 -0700
                                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:12 +0200
                                                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:10 +0200
                                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-29 10:18 -0700
                                                                  Re: Default values in #define already5chosen@yahoo.com - 2016-08-29 10:32 -0700
                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-08-29 10:49 -0700
                                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 23:13 +0200
                                                                    Re: Default values in #define supercat@casperkitty.com - 2016-08-29 14:48 -0700
                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-26 09:14 -0700
                                                      Re: Default values in #define supercat@casperkitty.com - 2016-08-26 08:59 -0700
                                                      Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:43 +0200
                                                        Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-29 22:58 -0700
                                                          Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-30 07:14 +0100
                                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-30 00:14 -0700
                                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 00:26 -0700
                                                              Re: Default values in #define already5chosen@yahoo.com - 2016-08-30 02:10 -0700
                                                              Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-30 10:47 +0100
                                                                Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 03:32 -0700
                                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:38 +0200
                                                                    Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 04:44 -0700
                                                                      Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 14:00 +0200
                                                                  Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-30 18:55 +0100
                                                                    Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 12:24 -0700
                                                                      Re: Default values in #define me <crisdunbar@gmail.com> - 2016-08-30 14:11 -0700
                                                                        Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 16:28 -0700
                                                                          Re: Default values in #define me <crisdunbar@gmail.com> - 2016-08-30 16:54 -0700
                                                                            Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-31 06:27 +0100
                                                                      Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-30 23:09 +0100
                                                                        Re: Default values in #define supercat@casperkitty.com - 2016-08-30 16:06 -0700
                                                              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:35 +0200
                                                          Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-30 13:30 +0200
                                                            Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-30 04:39 -0700
                                                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:40 +0200
                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 15:17 +0200
                                              Re: Default values in #define already5chosen@yahoo.com - 2016-08-29 06:47 -0700
                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:58 +0200
                                                  Re: Default values in #define already5chosen@yahoo.com - 2016-08-29 09:09 -0700
                                                    Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 23:16 +0200
                                                      Re: Default values in #define already5chosen@yahoo.com - 2016-08-31 02:02 -0700
                                                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-31 12:49 +0200
                                                          Re: Default values in #define supercat@casperkitty.com - 2016-08-31 09:02 -0700
                                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-25 10:31 +0200
                                          Re: Default values in #define supercat@casperkitty.com - 2016-08-25 10:01 -0700
                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:24 +0200
                                              Re: Default values in #define supercat@casperkitty.com - 2016-08-29 10:43 -0700
                                                Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 23:29 +0200
                                                  Re: Default values in #define supercat@casperkitty.com - 2016-08-29 16:27 -0700
                                          Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-25 10:02 -0700
                                            Re: Default values in #define supercat@casperkitty.com - 2016-08-25 10:33 -0700
                                              Re: Default values in #define "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-08-25 14:12 -0700
                                                Re: Default values in #define supercat@casperkitty.com - 2016-08-25 14:22 -0700
                                            Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-29 16:27 +0200
              Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-22 23:13 +0200
                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 14:39 -0700
                  Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 09:32 +0200
                    Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 05:33 -0700
                    Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-23 06:13 -0700
                      Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 06:22 -0700
                        Re: Default values in #define David Brown <david.brown@hesbynett.no> - 2016-08-23 16:13 +0200
                          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-23 07:35 -0700
                    Re: Default values in #define Gareth Owen <gwowen@gmail.com> - 2016-08-23 19:08 +0100
              Re: Default values in #define Rosario19 <Ros@invalid.invalid> - 2016-08-24 09:05 +0200
                Re: Default values in #define mark.bluemel@gmail.com - 2016-08-24 00:49 -0700
                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-24 05:40 -0700
      Re: Default values in #define BartC <bc@freeuk.com> - 2016-08-19 22:56 +0100
        Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-20 10:14 +1200
          Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-19 18:09 -0700
            Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-20 13:15 +1200
              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-19 19:10 -0700
                Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-20 14:50 +1200
              Re: Default values in #define BartC <bc@freeuk.com> - 2016-08-20 10:35 +0100
                Re: Default values in #define Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-08-20 03:13 -0700
                  Re: Default values in #define BartC <bc@freeuk.com> - 2016-08-20 12:24 +0100
                Re: Default values in #define Ian Collins <ian-news@hotmail.com> - 2016-08-21 00:14 +1200
                Re: Default values in #define gazelle@shell.xmission.com (Kenny McCormack) - 2016-08-20 14:13 +0000
                  Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 05:17 -0700
                Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-20 12:08 -0700
            Re: Default values in #define Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-08-20 14:06 +0100
              Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-20 12:14 -0700
    Re: Default values in #define Philipp Klaus Krause <pkk@spth.de> - 2016-08-21 12:51 +0200
      Re: Default values in #define "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-08-22 05:11 -0700

Page 12 of 18 — ← Prev page 1 … 10 11 [12] 13 14 … 18  Next page →


#92943

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-30 08:12 -0400
Message-ID<nq3t6f$lvh$1@jstuckle.eternal-september.org>
In reply to#92933
On 8/30/2016 7:21 AM, David Brown wrote:
> On 29/08/16 23:24, Jerry Stuckle wrote:
>> On 8/29/2016 5:16 PM, supercat@casperkitty.com wrote:
>>> On Monday, August 29, 2016 at 3:43:08 PM UTC-5, Jerry Stuckle wrote:
>>>> If the instruction disables interrupts for 16 cycles, and it is issued
>>>> every 15 cycles, by your definition the interrupts will never be
>>>> processed.  Otherwise the system wouldn't fulfill your "disabled for 16
>>>> cycles" requirement.
>>>
>>> Should I have been more explicit "disabled for 16 cycles, or sooner if
>>> another instruction enables interrupts"?  I would have thought the latter
>>> was implied.
>>>
>>
>> Make up your mind.  But once again you change the rules in the middle of
>> the game.
>>
>>>> It's one or the other.  Either it waits 16 cycles or it doesn't.  You
>>>> can't have it both ways.
>>>
>>> Up to 16 cycles, or shorter if the code doesn't want/need the full 16.
>>>
>>
>> See above.
>>
>>>>> Since one should not expect to be able to run an arbitrary piece of code
>>>>> within a short 15-cycle window, there should be no concern about a
>>>>> context which uses the instruction being nested within another context
>>>>> that expects interrupts to be disabled continuously throughout it, since
>>>>> whoever is writing the outer code should be aware of what's within it
>>>>> (note that the construct would really only be useful from within assembly
>>>>> code, or with a compiler mode that is documented as generating code in a
>>>>> very straightforward and predictable fashion).
>>>>>
>>>>
>>>> It doesn't need to run "an arbitrary piece of code".  It just needs to
>>>> keep reissuing the instruction.
>>>
>>> And each time it issues it, the instruction starts by processing any
>>> interrupts that have become pending since the last time the instruction
>>> was issued.
>>>
>>
>> And a solution to a problem which doesn't exist.  That's what semaphores
>> are for.
>>
>> And *no one except the kernel* should be able to disable interrupts,
>> even for a short period of time.  Even with your "rules" it can have a
>> detrimental performance on the system.
>>
>> From your updates, it's obvious you've never done any kernel programming
>> in the past.  It is an entirely different approach than application
>> programming.
>>
> 
> Actually, I think Supercat's idea here would have a great deal of
> practical use, though it is primarily for single core systems (or as an
> aid to making more general SMP locks and semaphores).  I have also
> thought for years that it would be a very useful type of instruction,
> especially for embedded systems (though I think 16 cycle disable is
> longer than necessary).
> 
> As usual, Jerry, you don't understand what is being suggested, and
> therefore insult people rather than attempting to think or to
> communicate like a normal person.  But let me try to re-phrase the idea,
> and see if you understand it.
> 
> 
> It is often important to be able to perform a sequence of operations in
> an atomic fashion.  There are a variety of methods for doing this, such
> as building primitives for locking from instructions such
> "compare-and-swap" and "store-with-reservation", carefully ordered
> memory accesses, or even special hardware to support semaphores.  All of
> these have disadvantages - there can be significant overhead, and
> perhaps trial-and-retry loops, which means that something as simple as
> an atomic double-word read or write takes many times longer than the
> non-atomic version.
> 
> In single processor systems, the easiest and most efficient way to
> handle this is often to disable interrupts temporarily, then restore
> them after the atomic operation.  This is a cornerstone of embedded
> programming, and on bigger systems (with a distinction between user
> modes and privileged modes) it is often used in the kernel-side
> implementation of the OS's locking mechanisms.
> 
> But manually enabling and disabling interrupts can be error-prone.  It
> can be difficult to ensure that the interrupt disabled time is minimised
> (to avoid extra latency for interrupt routines), and user-mode code
> generally cannot disable interrupts because the relevant instructions
> are privileged.
> 
> So the suggestion is for an instruction that will temporarily disable
> interrupts for a given number of clock cycles or instruction counts,
> after which they will automatically be restored to the previous state.
> The hardware would guarantee that pending interrupts are run before a
> new temporary interrupt disable instruction is run, thus ensuring that
> interrupts can't be blocked for more than the maximum specified time.
> 
> This would make atomic accesses and lock primitives very simple and
> efficient, and eliminate much of the overhead needed when these are
> handled from user-mode (at least in the common case when there is no
> conflict).  For single cpu embedded systems, it would be a great feature.
> 
> There would be complications, of course, such as how it would interact
> with non-maskable interrupts or faults.  But such issues can be solved.
> 
> For multi-cpu systems, it would be harder - ideally, the feature could
> be combined with locking of a small address range.  A little more
> thought would be needed in order to ensure that this would be fair, and
> one process could not make a denial-of-service attack on another process
> (at least, not in a worse way than it can today by grabbing locks).
> 

I understand exactly what is being suggested, David.  And I still think
it's a bad suggestion - open to all kinds of problems.

I've worked with a lot of good programmers on OS's and embedded systems
over the years.  They haven't had problems with disabling and
re-enabling interrupts - but then they don't normally have to do it very
often.  About the only time it is important is when they have to update
a data structure that is also used by an interrupt handler, and even
then it's often better to use mutexes to handle the operation rather
than disable all interrupts.  And yes, mutexes can be used in interrupt
handlers.

And even then, it's not possible to disable all interrupts.  Most
processors have non-maskable interrupts, which cannot be disabled.
These are important for things like a hardware interrupt.

Another problem here is how you and supercat want it to work.  You want
to disable it for 16 cycles.  That may not be enough, or it may be too
long.  If it's not enough, then you have to reissue it by the time 15
cycles have elapsed.  However, that leaves the system wide open to a
rogue application shutting the system out by continuing to disable
interrupts.  So you say "allow interrupts before disabling again".  But
now that destroys your atomic operation - an interrupt handler can get
in during that time and change things.

And as you mentioned - this would only work for single core and single
thread systems.  Although there are still a lot of single-core,
single-thread systems around, multi-core and multi-threaded processors
are becoming more and more prevalent, even in embedded systems.

No, it's a bad idea, and not required.  If the hardware manufacturers
thought it was a good idea, someone would have implemented it by now.
The fact no one has indicates they see the potential problems much
better than you do, and understand it's a problem that already has good
solutions.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92944

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-30 15:24 +0200
Message-ID<nq41f9$483$1@dont-email.me>
In reply to#92943
On 30/08/16 14:12, Jerry Stuckle wrote:
> On 8/30/2016 7:21 AM, David Brown wrote:
>> On 29/08/16 23:24, Jerry Stuckle wrote:
>>> On 8/29/2016 5:16 PM, supercat@casperkitty.com wrote:
>>>> On Monday, August 29, 2016 at 3:43:08 PM UTC-5, Jerry Stuckle wrote:
>>>>> If the instruction disables interrupts for 16 cycles, and it is issued
>>>>> every 15 cycles, by your definition the interrupts will never be
>>>>> processed.  Otherwise the system wouldn't fulfill your "disabled for 16
>>>>> cycles" requirement.
>>>>
>>>> Should I have been more explicit "disabled for 16 cycles, or sooner if
>>>> another instruction enables interrupts"?  I would have thought the latter
>>>> was implied.
>>>>
>>>
>>> Make up your mind.  But once again you change the rules in the middle of
>>> the game.
>>>
>>>>> It's one or the other.  Either it waits 16 cycles or it doesn't.  You
>>>>> can't have it both ways.
>>>>
>>>> Up to 16 cycles, or shorter if the code doesn't want/need the full 16.
>>>>
>>>
>>> See above.
>>>
>>>>>> Since one should not expect to be able to run an arbitrary piece of code
>>>>>> within a short 15-cycle window, there should be no concern about a
>>>>>> context which uses the instruction being nested within another context
>>>>>> that expects interrupts to be disabled continuously throughout it, since
>>>>>> whoever is writing the outer code should be aware of what's within it
>>>>>> (note that the construct would really only be useful from within assembly
>>>>>> code, or with a compiler mode that is documented as generating code in a
>>>>>> very straightforward and predictable fashion).
>>>>>>
>>>>>
>>>>> It doesn't need to run "an arbitrary piece of code".  It just needs to
>>>>> keep reissuing the instruction.
>>>>
>>>> And each time it issues it, the instruction starts by processing any
>>>> interrupts that have become pending since the last time the instruction
>>>> was issued.
>>>>
>>>
>>> And a solution to a problem which doesn't exist.  That's what semaphores
>>> are for.
>>>
>>> And *no one except the kernel* should be able to disable interrupts,
>>> even for a short period of time.  Even with your "rules" it can have a
>>> detrimental performance on the system.
>>>
>>> From your updates, it's obvious you've never done any kernel programming
>>> in the past.  It is an entirely different approach than application
>>> programming.
>>>
>>
>> Actually, I think Supercat's idea here would have a great deal of
>> practical use, though it is primarily for single core systems (or as an
>> aid to making more general SMP locks and semaphores).  I have also
>> thought for years that it would be a very useful type of instruction,
>> especially for embedded systems (though I think 16 cycle disable is
>> longer than necessary).
>>
>> As usual, Jerry, you don't understand what is being suggested, and
>> therefore insult people rather than attempting to think or to
>> communicate like a normal person.  But let me try to re-phrase the idea,
>> and see if you understand it.
>>
>>
>> It is often important to be able to perform a sequence of operations in
>> an atomic fashion.  There are a variety of methods for doing this, such
>> as building primitives for locking from instructions such
>> "compare-and-swap" and "store-with-reservation", carefully ordered
>> memory accesses, or even special hardware to support semaphores.  All of
>> these have disadvantages - there can be significant overhead, and
>> perhaps trial-and-retry loops, which means that something as simple as
>> an atomic double-word read or write takes many times longer than the
>> non-atomic version.
>>
>> In single processor systems, the easiest and most efficient way to
>> handle this is often to disable interrupts temporarily, then restore
>> them after the atomic operation.  This is a cornerstone of embedded
>> programming, and on bigger systems (with a distinction between user
>> modes and privileged modes) it is often used in the kernel-side
>> implementation of the OS's locking mechanisms.
>>
>> But manually enabling and disabling interrupts can be error-prone.  It
>> can be difficult to ensure that the interrupt disabled time is minimised
>> (to avoid extra latency for interrupt routines), and user-mode code
>> generally cannot disable interrupts because the relevant instructions
>> are privileged.
>>
>> So the suggestion is for an instruction that will temporarily disable
>> interrupts for a given number of clock cycles or instruction counts,
>> after which they will automatically be restored to the previous state.
>> The hardware would guarantee that pending interrupts are run before a
>> new temporary interrupt disable instruction is run, thus ensuring that
>> interrupts can't be blocked for more than the maximum specified time.
>>
>> This would make atomic accesses and lock primitives very simple and
>> efficient, and eliminate much of the overhead needed when these are
>> handled from user-mode (at least in the common case when there is no
>> conflict).  For single cpu embedded systems, it would be a great feature.
>>
>> There would be complications, of course, such as how it would interact
>> with non-maskable interrupts or faults.  But such issues can be solved.
>>
>> For multi-cpu systems, it would be harder - ideally, the feature could
>> be combined with locking of a small address range.  A little more
>> thought would be needed in order to ensure that this would be fair, and
>> one process could not make a denial-of-service attack on another process
>> (at least, not in a worse way than it can today by grabbing locks).
>>
> 
> I understand exactly what is being suggested, David.  And I still think
> it's a bad suggestion - open to all kinds of problems.
> 

It is not a golden bullet, and yes, there would be complications.  But
it would be another useful tool.

> I've worked with a lot of good programmers on OS's and embedded systems
> over the years.  They haven't had problems with disabling and
> re-enabling interrupts - but then they don't normally have to do it very
> often.  About the only time it is important is when they have to update
> a data structure that is also used by an interrupt handler, and even
> then it's often better to use mutexes to handle the operation rather
> than disable all interrupts.  And yes, mutexes can be used in interrupt
> handlers.

On a larger system with a bigger OS, perhaps multiple cores, and many
developers that need strict interfaces between different parts of the
code - then yes, mutexes or other higher level locking mechanisms are
often best.  (And I agree that some types of locks or mutexes can be
used in interrupts, as long as you have the right kind of locks and use
them in the right way.)

But these mechanisms can quickly have much more overhead than a simple
"disable global interrupts, do the job, re-enable interrupt status".
For small job, such as atomically incrementing a counter, you could be
talking about hundreds of times larger overhead.

This is the way it is done on most small systems, and it often forms a
key part of higher-level synchronisation mechanisms.  It can even be a
more efficient mechanism on processors with compare-and-swap or
load-store "reservation" instructions.

> 
> And even then, it's not possible to disable all interrupts.  Most
> processors have non-maskable interrupts, which cannot be disabled.
> These are important for things like a hardware interrupt.

In most cases on small systems, you /can/ disable almost all interrupts.
 Non-maskable interrupts are rarely used, except perhaps for extreme
situations (like power-fail interrupts).  Bigger systems may be more
complicated, of course.

> 
> Another problem here is how you and supercat want it to work.  You want
> to disable it for 16 cycles.  That may not be enough, or it may be too
> long.  If it's not enough, then you have to reissue it by the time 15
> cycles have elapsed.  However, that leaves the system wide open to a
> rogue application shutting the system out by continuing to disable
> interrupts.  So you say "allow interrupts before disabling again".  But
> now that destroys your atomic operation - an interrupt handler can get
> in during that time and change things.

I don't want to allow a restart of the counter before interrupts are
re-enabled - if you issue a new temporary interrupt disable counter
instruction before the previous one runs out, you get pending interrupts
at that point before the counter is restarted.  That is your protection
against unexpected interrupt latency.  The 16 cycles (which may be clock
cycles, or instruction counts) should be plenty of simple locking - and
if you need more, you use the simple locks to build your big locks, or
you go back to old-fashioned interrupt disable code.

> 
> And as you mentioned - this would only work for single core and single
> thread systems.  Although there are still a lot of single-core,
> single-thread systems around, multi-core and multi-threaded processors
> are becoming more and more prevalent, even in embedded systems.

It will be fine for multiple threads on the single core processor - it
is only when you have multiple cores or virtual cores that there is a
problem.  And while I agree that multi-core processors are becoming more
common in embedded systems, the /huge/ majority of embedded
microcontrollers are single core (or non-SMP multi-core, where you
effectively have two independent systems on the same chip).

> 
> No, it's a bad idea, and not required.  If the hardware manufacturers
> thought it was a good idea, someone would have implemented it by now.
> The fact no one has indicates they see the potential problems much
> better than you do, and understand it's a problem that already has good
> solutions.
> 

I agree it is not a required feature - after all, we got on fine without
it.  And there would be complications in implementing it in hardware, it
would not scale to multi-core systems, and it would be less useful and
more complicated with superscaler processors.  But for smaller systems
and simpler microcontrollers, it would definitely be a useful feature.
Whether or not it would be cost-effective (no feature is free) is
another matter.




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


#92949

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-30 10:53 -0400
Message-ID<nq46li$ll4$1@jstuckle.eternal-september.org>
In reply to#92944
On 8/30/2016 9:24 AM, David Brown wrote:
> On 30/08/16 14:12, Jerry Stuckle wrote:
>> On 8/30/2016 7:21 AM, David Brown wrote:
>>> On 29/08/16 23:24, Jerry Stuckle wrote:
>>>> On 8/29/2016 5:16 PM, supercat@casperkitty.com wrote:
>>>>> On Monday, August 29, 2016 at 3:43:08 PM UTC-5, Jerry Stuckle wrote:
>>>>>> If the instruction disables interrupts for 16 cycles, and it is issued
>>>>>> every 15 cycles, by your definition the interrupts will never be
>>>>>> processed.  Otherwise the system wouldn't fulfill your "disabled for 16
>>>>>> cycles" requirement.
>>>>>
>>>>> Should I have been more explicit "disabled for 16 cycles, or sooner if
>>>>> another instruction enables interrupts"?  I would have thought the latter
>>>>> was implied.
>>>>>
>>>>
>>>> Make up your mind.  But once again you change the rules in the middle of
>>>> the game.
>>>>
>>>>>> It's one or the other.  Either it waits 16 cycles or it doesn't.  You
>>>>>> can't have it both ways.
>>>>>
>>>>> Up to 16 cycles, or shorter if the code doesn't want/need the full 16.
>>>>>
>>>>
>>>> See above.
>>>>
>>>>>>> Since one should not expect to be able to run an arbitrary piece of code
>>>>>>> within a short 15-cycle window, there should be no concern about a
>>>>>>> context which uses the instruction being nested within another context
>>>>>>> that expects interrupts to be disabled continuously throughout it, since
>>>>>>> whoever is writing the outer code should be aware of what's within it
>>>>>>> (note that the construct would really only be useful from within assembly
>>>>>>> code, or with a compiler mode that is documented as generating code in a
>>>>>>> very straightforward and predictable fashion).
>>>>>>>
>>>>>>
>>>>>> It doesn't need to run "an arbitrary piece of code".  It just needs to
>>>>>> keep reissuing the instruction.
>>>>>
>>>>> And each time it issues it, the instruction starts by processing any
>>>>> interrupts that have become pending since the last time the instruction
>>>>> was issued.
>>>>>
>>>>
>>>> And a solution to a problem which doesn't exist.  That's what semaphores
>>>> are for.
>>>>
>>>> And *no one except the kernel* should be able to disable interrupts,
>>>> even for a short period of time.  Even with your "rules" it can have a
>>>> detrimental performance on the system.
>>>>
>>>> From your updates, it's obvious you've never done any kernel programming
>>>> in the past.  It is an entirely different approach than application
>>>> programming.
>>>>
>>>
>>> Actually, I think Supercat's idea here would have a great deal of
>>> practical use, though it is primarily for single core systems (or as an
>>> aid to making more general SMP locks and semaphores).  I have also
>>> thought for years that it would be a very useful type of instruction,
>>> especially for embedded systems (though I think 16 cycle disable is
>>> longer than necessary).
>>>
>>> As usual, Jerry, you don't understand what is being suggested, and
>>> therefore insult people rather than attempting to think or to
>>> communicate like a normal person.  But let me try to re-phrase the idea,
>>> and see if you understand it.
>>>
>>>
>>> It is often important to be able to perform a sequence of operations in
>>> an atomic fashion.  There are a variety of methods for doing this, such
>>> as building primitives for locking from instructions such
>>> "compare-and-swap" and "store-with-reservation", carefully ordered
>>> memory accesses, or even special hardware to support semaphores.  All of
>>> these have disadvantages - there can be significant overhead, and
>>> perhaps trial-and-retry loops, which means that something as simple as
>>> an atomic double-word read or write takes many times longer than the
>>> non-atomic version.
>>>
>>> In single processor systems, the easiest and most efficient way to
>>> handle this is often to disable interrupts temporarily, then restore
>>> them after the atomic operation.  This is a cornerstone of embedded
>>> programming, and on bigger systems (with a distinction between user
>>> modes and privileged modes) it is often used in the kernel-side
>>> implementation of the OS's locking mechanisms.
>>>
>>> But manually enabling and disabling interrupts can be error-prone.  It
>>> can be difficult to ensure that the interrupt disabled time is minimised
>>> (to avoid extra latency for interrupt routines), and user-mode code
>>> generally cannot disable interrupts because the relevant instructions
>>> are privileged.
>>>
>>> So the suggestion is for an instruction that will temporarily disable
>>> interrupts for a given number of clock cycles or instruction counts,
>>> after which they will automatically be restored to the previous state.
>>> The hardware would guarantee that pending interrupts are run before a
>>> new temporary interrupt disable instruction is run, thus ensuring that
>>> interrupts can't be blocked for more than the maximum specified time.
>>>
>>> This would make atomic accesses and lock primitives very simple and
>>> efficient, and eliminate much of the overhead needed when these are
>>> handled from user-mode (at least in the common case when there is no
>>> conflict).  For single cpu embedded systems, it would be a great feature.
>>>
>>> There would be complications, of course, such as how it would interact
>>> with non-maskable interrupts or faults.  But such issues can be solved.
>>>
>>> For multi-cpu systems, it would be harder - ideally, the feature could
>>> be combined with locking of a small address range.  A little more
>>> thought would be needed in order to ensure that this would be fair, and
>>> one process could not make a denial-of-service attack on another process
>>> (at least, not in a worse way than it can today by grabbing locks).
>>>
>>
>> I understand exactly what is being suggested, David.  And I still think
>> it's a bad suggestion - open to all kinds of problems.
>>
> 
> It is not a golden bullet, and yes, there would be complications.  But
> it would be another useful tool.
> 
>> I've worked with a lot of good programmers on OS's and embedded systems
>> over the years.  They haven't had problems with disabling and
>> re-enabling interrupts - but then they don't normally have to do it very
>> often.  About the only time it is important is when they have to update
>> a data structure that is also used by an interrupt handler, and even
>> then it's often better to use mutexes to handle the operation rather
>> than disable all interrupts.  And yes, mutexes can be used in interrupt
>> handlers.
> 
> On a larger system with a bigger OS, perhaps multiple cores, and many
> developers that need strict interfaces between different parts of the
> code - then yes, mutexes or other higher level locking mechanisms are
> often best.  (And I agree that some types of locks or mutexes can be
> used in interrupts, as long as you have the right kind of locks and use
> them in the right way.)
> 
> But these mechanisms can quickly have much more overhead than a simple
> "disable global interrupts, do the job, re-enable interrupt status".
> For small job, such as atomically incrementing a counter, you could be
> talking about hundreds of times larger overhead.
>

Not necessarily. Most systems have atomic operations for something like
incrementing a counter.  After all, similar operations are used to
create mutexes.  And even if not, mutexes locking and unlocking mutexes
is a highly optimized operation in any OS I've seen - often as little as
a half-dozen machine instructions or less, which can generally be
implemented inline via a macro.

> This is the way it is done on most small systems, and it often forms a
> key part of higher-level synchronisation mechanisms.  It can even be a
> more efficient mechanism on processors with compare-and-swap or
> load-store "reservation" instructions.
> 

Yes, which is how mutexes are locked in such systems.  It's pretty fast.

>>
>> And even then, it's not possible to disable all interrupts.  Most
>> processors have non-maskable interrupts, which cannot be disabled.
>> These are important for things like a hardware interrupt.
> 
> In most cases on small systems, you /can/ disable almost all interrupts.
>  Non-maskable interrupts are rarely used, except perhaps for extreme
> situations (like power-fail interrupts).  Bigger systems may be more
> complicated, of course.
> 

"Almost" is not "all".  And they still have to be considered.  Failure
to do things like this is a common cause of design bugs.

>>
>> Another problem here is how you and supercat want it to work.  You want
>> to disable it for 16 cycles.  That may not be enough, or it may be too
>> long.  If it's not enough, then you have to reissue it by the time 15
>> cycles have elapsed.  However, that leaves the system wide open to a
>> rogue application shutting the system out by continuing to disable
>> interrupts.  So you say "allow interrupts before disabling again".  But
>> now that destroys your atomic operation - an interrupt handler can get
>> in during that time and change things.
> 
> I don't want to allow a restart of the counter before interrupts are
> re-enabled - if you issue a new temporary interrupt disable counter
> instruction before the previous one runs out, you get pending interrupts
> at that point before the counter is restarted.  That is your protection
> against unexpected interrupt latency.  The 16 cycles (which may be clock
> cycles, or instruction counts) should be plenty of simple locking - and
> if you need more, you use the simple locks to build your big locks, or
> you go back to old-fashioned interrupt disable code.
> 

Which then means your update is no longer atomic.  Something can get in
in the middle and change things.  And 16 instruction cycles is more than
it takes to lock and unlock a mutex in many systems.

>>
>> And as you mentioned - this would only work for single core and single
>> thread systems.  Although there are still a lot of single-core,
>> single-thread systems around, multi-core and multi-threaded processors
>> are becoming more and more prevalent, even in embedded systems.
> 
> It will be fine for multiple threads on the single core processor - it
> is only when you have multiple cores or virtual cores that there is a
> problem.  And while I agree that multi-core processors are becoming more
> common in embedded systems, the /huge/ majority of embedded
> microcontrollers are single core (or non-SMP multi-core, where you
> effectively have two independent systems on the same chip).
> 

Ah, but you can also have multithreading on a single core system, ala
Intel's hyper-threading, which allows two virtual cores on one real core.

>>
>> No, it's a bad idea, and not required.  If the hardware manufacturers
>> thought it was a good idea, someone would have implemented it by now.
>> The fact no one has indicates they see the potential problems much
>> better than you do, and understand it's a problem that already has good
>> solutions.
>>
> 
> I agree it is not a required feature - after all, we got on fine without
> it.  And there would be complications in implementing it in hardware, it
> would not scale to multi-core systems, and it would be less useful and
> more complicated with superscaler processors.  But for smaller systems
> and simpler microcontrollers, it would definitely be a useful feature.
> Whether or not it would be cost-effective (no feature is free) is
> another matter.
> 

I just see too many downsides to this and no real upside - other than
not wanting to ensure you've enabled interrupts after disabling them.

But then I almost never disable interrupts, even in kernel code (and
never in application code).  It's just so rarely necessary.  If you find
you are doing so regularly, you need to be looking at why.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92952

Fromsupercat@casperkitty.com
Date2016-08-30 10:34 -0700
Message-ID<0ea839c1-2a9d-4880-a126-a8e0265b505e@googlegroups.com>
In reply to#92949
On Tuesday, August 30, 2016 at 9:53:47 AM UTC-5, Jerry Stuckle wrote:
> On 8/30/2016 9:24 AM, David Brown wrote:
> > This is the way it is done on most small systems, and it often forms a
> > key part of higher-level synchronisation mechanisms.  It can even be a
> > more efficient mechanism on processors with compare-and-swap or
> > load-store "reservation" instructions.
> 
> Yes, which is how mutexes are locked in such systems.  It's pretty fast.

LDREX/STREX is generally pretty fast for handling updates to a single object,
but are a bit awkward for updates that need to hit two things at once.
It's possible to leverage a 32-bit LDREX and memory barriers to atomically
update a 64-bit value among threads, but it's pretty complicated.  Having
a quick sequence to disable interrupts, update the counter, and re-enable
interrupts would make things much easier.  Doubly-linked-list updates can
be handled smoothly with LDREX/STREX if code that uses backward links always
double-checks their validity, but being able to disable interrupts long
enough to do an update would greatly simplify them.

> > In most cases on small systems, you /can/ disable almost all interrupts.
> >  Non-maskable interrupts are rarely used, except perhaps for extreme
> > situations (like power-fail interrupts).  Bigger systems may be more
> > complicated, of course.

> "Almost" is not "all".  And they still have to be considered.  Failure
> to do things like this is a common cause of design bugs.

One should not expect all features to be useful for all applications.
There are many cases where the only interrupts that could not be disabled
are those from things like bus errors, and where all such interrupts are
allowed to severely disrupt the execution state (e.g. where the system is
going to be restarted or shut down).

In designing a system it would likely be necessary to decide in advance
whether it will ever need virtual memory or symmetric multiprocessing,
since use of a short-term interrupt-disable feature would make it more
difficult to adapt the system to use either of those things.  In cases
where there is no realistic future need for such features, however, things
could be simplified.

> > I don't want to allow a restart of the counter before interrupts are
> > re-enabled - if you issue a new temporary interrupt disable counter
> > instruction before the previous one runs out, you get pending interrupts
> > at that point before the counter is restarted.  That is your protection
> > against unexpected interrupt latency.  The 16 cycles (which may be clock
> > cycles, or instruction counts) should be plenty of simple locking - and
> > if you need more, you use the simple locks to build your big locks, or
> > you go back to old-fashioned interrupt disable code.
> 
> Which then means your update is no longer atomic.  Something can get in
> in the middle and change things.  And 16 instruction cycles is more than
> it takes to lock and unlock a mutex in many systems.

If you have a sequence of instructions which is preceded by a temporary-
interrupt-disable function, fits within its time limit, and does not include
another temporary-interrupt-disable function, the sequence will be atomic.
The intended duration would be sufficient to allow code with a pointer to an
existing node in R0 and a pointer to a desired new node in R1, R2 holds the
expected value in [R3] (an "updates" counter)

     ADD R4,R2,#1
     LDR R6,[R0+NextPtr]  ; Get existing->next
     SUSPIRQ ; Temporarily suspend interrupt processing
     LDR R5,[R3]
     CMP R5,R2
     BNE Oops
     STR R4,[R3]
     STR R6,[R1+NextPtr]  ; Set newnode->next to existing->next
     STR R0,[R1+PrevPtr]  ; Set newnode->next to existing
     STR R1,[R0+NextPtr]  ; Set current->next to new node
     STR R1,[R6+PrevPtr]  ; Set existing->next->prev to new node

At two cycles per load or store, and one for each compare or
branch-not-taken, that would put 14 cycles in the critical section.

> I just see too many downsides to this and no real upside - other than
> not wanting to ensure you've enabled interrupts after disabling them.

The upside would be the ability to have user code disable interrupts for
a short time without requiring a context switch to supervisor mode.

> But then I almost never disable interrupts, even in kernel code (and
> never in application code).  It's just so rarely necessary.  If you find
> you are doing so regularly, you need to be looking at why.

It's a fast way to perform atomic updates on single-processor systems.

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


#92955

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-30 14:44 -0400
Message-ID<nq4k6e$782$1@jstuckle.eternal-september.org>
In reply to#92952
On 8/30/2016 1:34 PM, supercat@casperkitty.com wrote:
> On Tuesday, August 30, 2016 at 9:53:47 AM UTC-5, Jerry Stuckle wrote:
>> On 8/30/2016 9:24 AM, David Brown wrote:
>>> This is the way it is done on most small systems, and it often forms a
>>> key part of higher-level synchronisation mechanisms.  It can even be a
>>> more efficient mechanism on processors with compare-and-swap or
>>> load-store "reservation" instructions.
>>
>> Yes, which is how mutexes are locked in such systems.  It's pretty fast.
> 
> LDREX/STREX is generally pretty fast for handling updates to a single object,
> but are a bit awkward for updates that need to hit two things at once.
> It's possible to leverage a 32-bit LDREX and memory barriers to atomically
> update a 64-bit value among threads, but it's pretty complicated.  Having
> a quick sequence to disable interrupts, update the counter, and re-enable
> interrupts would make things much easier.  Doubly-linked-list updates can
> be handled smoothly with LDREX/STREX if code that uses backward links always
> double-checks their validity, but being able to disable interrupts long
> enough to do an update would greatly simplify them.
>

And once again, if it takes more than (x) cycles to process, you need to
disable interrupts twice.  And you can't allow interrupts to proceed
between the two calls, because your update is no longer atomic.  But to
not allow interrupts between successive calls means a bad application
can lock the system.

And there are easy ways around the problem already.  They're called
mutex semaphores.

>>> In most cases on small systems, you /can/ disable almost all interrupts.
>>>  Non-maskable interrupts are rarely used, except perhaps for extreme
>>> situations (like power-fail interrupts).  Bigger systems may be more
>>> complicated, of course.
> 
>> "Almost" is not "all".  And they still have to be considered.  Failure
>> to do things like this is a common cause of design bugs.
> 
> One should not expect all features to be useful for all applications.
> There are many cases where the only interrupts that could not be disabled
> are those from things like bus errors, and where all such interrupts are
> allowed to severely disrupt the execution state (e.g. where the system is
> going to be restarted or shut down).
> 

In this case, you need to consider ALL - because ALL chips have
non-maskable interrupts.  Bus errors and the like are not the only
reasons for this happening.

And it still doesn't solve the problem in a multi-threaded system.

> In designing a system it would likely be necessary to decide in advance
> whether it will ever need virtual memory or symmetric multiprocessing,
> since use of a short-term interrupt-disable feature would make it more
> difficult to adapt the system to use either of those things.  In cases
> where there is no realistic future need for such features, however, things
> could be simplified.
> 

Not only difficult - it would be virtually impossible to do it on a
system with virtual memory.  After all, page fault is an interrupt.  And
you don't need symmetric multiprocessing to cause a problem - even
hyper-threading can cause problems.

But then there are much better ways to handle this already, as noted above.

>>> I don't want to allow a restart of the counter before interrupts are
>>> re-enabled - if you issue a new temporary interrupt disable counter
>>> instruction before the previous one runs out, you get pending interrupts
>>> at that point before the counter is restarted.  That is your protection
>>> against unexpected interrupt latency.  The 16 cycles (which may be clock
>>> cycles, or instruction counts) should be plenty of simple locking - and
>>> if you need more, you use the simple locks to build your big locks, or
>>> you go back to old-fashioned interrupt disable code.
>>
>> Which then means your update is no longer atomic.  Something can get in
>> in the middle and change things.  And 16 instruction cycles is more than
>> it takes to lock and unlock a mutex in many systems.
> 
> If you have a sequence of instructions which is preceded by a temporary-
> interrupt-disable function, fits within its time limit, and does not include
> another temporary-interrupt-disable function, the sequence will be atomic.
> The intended duration would be sufficient to allow code with a pointer to an
> existing node in R0 and a pointer to a desired new node in R1, R2 holds the
> expected value in [R3] (an "updates" counter)
> 
>      ADD R4,R2,#1
>      LDR R6,[R0+NextPtr]  ; Get existing->next
>      SUSPIRQ ; Temporarily suspend interrupt processing
>      LDR R5,[R3]
>      CMP R5,R2
>      BNE Oops
>      STR R4,[R3]
>      STR R6,[R1+NextPtr]  ; Set newnode->next to existing->next
>      STR R0,[R1+PrevPtr]  ; Set newnode->next to existing
>      STR R1,[R0+NextPtr]  ; Set current->next to new node
>      STR R1,[R6+PrevPtr]  ; Set existing->next->prev to new node
> 
> At two cycles per load or store, and one for each compare or
> branch-not-taken, that would put 14 cycles in the critical section.
> 

Only true if you're not multithreading.  But you're also assuming
specific machine cycles for each of these.  That makes your code even
more fragile.  What happens, for instance, when a new processor comes
out and you need three cycles per load or store?  Or someone takes your
code and puts it in a multi-threaded system?  Or one with virtual
memory?  Now it's even more fragile than before.

A much better way is to just lock a mutex before you start, and unlock
it after you're done.  And each access to the protected area is guarded
by the same mutex.  It's not hard, and it's not very time consuming.

>> I just see too many downsides to this and no real upside - other than
>> not wanting to ensure you've enabled interrupts after disabling them.
> 
> The upside would be the ability to have user code disable interrupts for
> a short time without requiring a context switch to supervisor mode.
> 

If you're updating something that can also be updated by an interrupt,
chances are you're already in supervisor mode to even access that
memory.  That's how the small embedded systems work.  And in that case,
a mutex is generally less than 5 or so instructions to lock or unlock -
which can be placed in a macro.

>> But then I almost never disable interrupts, even in kernel code (and
>> never in application code).  It's just so rarely necessary.  If you find
>> you are doing so regularly, you need to be looking at why.
> 
> It's a fast way to perform atomic updates on single-processor systems.
> 

I see no real gain over a mutex.  It looks more like a lazy way to
perform atomic updates on a single-processor system (which may still be
multi-threaded - see Intel's hyper-threading for an example) under the
guise of premature optimization.

And much better ways are already available - which is why I think NO
processor manufacturer has ever implemented such a choice.  If it were
such a good idea, someone surely would have done so.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92960

Fromsupercat@casperkitty.com
Date2016-08-30 12:48 -0700
Message-ID<d741fcbf-e2a3-44a0-9740-e9049563c865@googlegroups.com>
In reply to#92955
On Tuesday, August 30, 2016 at 1:44:42 PM UTC-5, Jerry Stuckle wrote:
> And once again, if it takes more than (x) cycles to process, you need to
> disable interrupts twice.  And you can't allow interrupts to proceed
> between the two calls, because your update is no longer atomic.  But to
> not allow interrupts between successive calls means a bad application
> can lock the system.

The purpose of the construct would be allow user-mode code to perform
certain kinds of simple atomic updates which are presently awkward.  If
an interrupt that might want to use a resource cannot be blocked while
the resource is being updated, it will be necessary to have the interrupt
return control to the mainline code without having used the resource but
somehow acquire control once the mainline code is done with it.

> And there are easy ways around the problem already.  They're called
> mutex semaphores.

They work much well with threads, but poorly with interrupts.  If the
mainline uses locks when e.g. adding something to a linked list and an
interrupt needs to make use of that list, there won't be much the interrupt
handler can do if it is invoked while the list is locked.  The best it may
be able to do would be to set up some other interrupt handler to finish
the job once the list is unlocked, but that's nowhere near as practical as
delaying the invocation of the interrupt until the list is ready.  The
question is whether user-mode code should be able to handle simple update
cases without a context switch to supervisor mode.

> > One should not expect all features to be useful for all applications.
> > There are many cases where the only interrupts that could not be disabled
> > are those from things like bus errors, and where all such interrupts are
> > allowed to severely disrupt the execution state (e.g. where the system is
> > going to be restarted or shut down).
> 
> In this case, you need to consider ALL - because ALL chips have
> non-maskable interrupts.  Bus errors and the like are not the only
> reasons for this happening.

Some chips don't have any non-maskable interrupts, and many designs for
chips that do have NMI inputs have them permanently strapped inactive.
Otherwise, if a chip is going to save a 32-bits processor status word
where most bits are unused, using four (or so) otherwise-unused bits to
report whether and for low long low-priority interrupts were disabled
would take care of the issue provided the NMI didn't need to use the
contended resource.

> And it still doesn't solve the problem in a multi-threaded system.

If only a single core is used to access the contended resource, and if
disabling interrupts also disables context switching, what problem would
remain?  The approach wouldn't work very well in fancier systems, but on
the flip side fancier systems already have other ways to accomplish the
same purposes.  The design would offer the most benefit in systems that
would not otherwise need pre-emptive threading.

> > In designing a system it would likely be necessary to decide in advance
> > whether it will ever need virtual memory or symmetric multiprocessing,
> > since use of a short-term interrupt-disable feature would make it more
> > difficult to adapt the system to use either of those things.  In cases
> > where there is no realistic future need for such features, however, things
> > could be simplified.
> 
> Not only difficult - it would be virtually impossible to do it on a
> system with virtual memory.  After all, page fault is an interrupt.  And
> you don't need symmetric multiprocessing to cause a problem - even
> hyper-threading can cause problems.

I would regard a hyper-threading system that treats virtual cores
interchangeably as symmetric multiprocessing, as distinct from a system
which assigns different cores (virtual or otherwise) to different hard-
coded purposes.

If most contested resources will only be used by a single core, that should
greatly ease the amount of logic needed to synchronize access to those
resources.  Resources that are shared between cores will need more complex
logic, but being able to simplify most of the logic is better than not being
able to simplify any.

> Only true if you're not multithreading.  But you're also assuming
> specific machine cycles for each of these.  That makes your code even
> more fragile.  What happens, for instance, when a new processor comes
> out and you need three cycles per load or store?  Or someone takes your
> code and puts it in a multi-threaded system?  Or one with virtual
> memory?  Now it's even more fragile than before.

There are a variety of ways such things could be handled, e.g. by
specifying the amount by which the "IRQ suspended" counter will be
decremented after each particular instruction (possibly 1 for each
instruction, or maybe more for "expensive" instructions).

Besides, it's no different from any other decision to use a hardware feature
that is available on some platforms and not others.  Code which is moved
to a platform that doesn't support the feature will need to be reworked.

> A much better way is to just lock a mutex before you start, and unlock
> it after you're done.  And each access to the protected area is guarded
> by the same mutex.  It's not hard, and it's not very time consuming.

And what do you do if an interrupt handler needs something whose mutex is
busy?

> If you're updating something that can also be updated by an interrupt,
> chances are you're already in supervisor mode to even access that
> memory.  That's how the small embedded systems work.  And in that case,
> a mutex is generally less than 5 or so instructions to lock or unlock -
> which can be placed in a macro.

That isn't necessarily true.  It's not uncommon for interrupt handlers
to use buffers and other data structures that can be placed anywhere in
memory.  The pointers that say where those things go may be accessible
only in supervisor mode, but the objects themselves may be wherever the
client code wants them.

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


#92963

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-30 17:19 -0400
Message-ID<nq4t89$8m0$1@jstuckle.eternal-september.org>
In reply to#92960
On 8/30/2016 3:48 PM, supercat@casperkitty.com wrote:
> On Tuesday, August 30, 2016 at 1:44:42 PM UTC-5, Jerry Stuckle wrote:
>> And once again, if it takes more than (x) cycles to process, you need to
>> disable interrupts twice.  And you can't allow interrupts to proceed
>> between the two calls, because your update is no longer atomic.  But to
>> not allow interrupts between successive calls means a bad application
>> can lock the system.
> 
> The purpose of the construct would be allow user-mode code to perform
> certain kinds of simple atomic updates which are presently awkward.  If
> an interrupt that might want to use a resource cannot be blocked while
> the resource is being updated, it will be necessary to have the interrupt
> return control to the mainline code without having used the resource but
> somehow acquire control once the mainline code is done with it.
>

But once again - user mode does not generally access the same buffers as
interrupts - they operate in supervisor (kernel) mode.  If the
application accesses the buffer, it will almost always be in supervisor
mode.

And in either user or supervisor mode, a mutex will block the interrupt
thread from updating it, but on release of the mutex, the interrupt
thread will be allowed to continue.

So there is no real problem.

>> And there are easy ways around the problem already.  They're called
>> mutex semaphores.
> 
> They work much well with threads, but poorly with interrupts.  If the
> mainline uses locks when e.g. adding something to a linked list and an
> interrupt needs to make use of that list, there won't be much the interrupt
> handler can do if it is invoked while the list is locked.  The best it may
> be able to do would be to set up some other interrupt handler to finish
> the job once the list is unlocked, but that's nowhere near as practical as
> delaying the invocation of the interrupt until the list is ready.  The
> question is whether user-mode code should be able to handle simple update
> cases without a context switch to supervisor mode.
> 

They work quite well with interrupts.  Of course the interrupt handler
will not be able to update the list - but it can be designed so that
it's not a problem.

And once again - the interrupt handler is running in supervisor mode,
accessing physical memory.  If there is a user application accessing the
same memory, it is going to be running in supervisor mode, also - not
user mode.

>>> One should not expect all features to be useful for all applications.
>>> There are many cases where the only interrupts that could not be disabled
>>> are those from things like bus errors, and where all such interrupts are
>>> allowed to severely disrupt the execution state (e.g. where the system is
>>> going to be restarted or shut down).
>>
>> In this case, you need to consider ALL - because ALL chips have
>> non-maskable interrupts.  Bus errors and the like are not the only
>> reasons for this happening.
> 
> Some chips don't have any non-maskable interrupts, and many designs for
> chips that do have NMI inputs have them permanently strapped inactive.
> Otherwise, if a chip is going to save a 32-bits processor status word
> where most bits are unused, using four (or so) otherwise-unused bits to
> report whether and for low long low-priority interrupts were disabled
> would take care of the issue provided the NMI didn't need to use the
> contended resource.
> 

I don't know of any chips which don't have NMIs, or any *good* designs
which strap them inactive.  I admit I don't know all chips or all
designs - but there are valid reasons for having the NMIs - like an
emergency reset of the system.

>> And it still doesn't solve the problem in a multi-threaded system.
> 
> If only a single core is used to access the contended resource, and if
> disabling interrupts also disables context switching, what problem would
> remain?  The approach wouldn't work very well in fancier systems, but on
> the flip side fancier systems already have other ways to accomplish the
> same purposes.  The design would offer the most benefit in systems that
> would not otherwise need pre-emptive threading.
>

You need to read up on hyper-threading.

>>> In designing a system it would likely be necessary to decide in advance
>>> whether it will ever need virtual memory or symmetric multiprocessing,
>>> since use of a short-term interrupt-disable feature would make it more
>>> difficult to adapt the system to use either of those things.  In cases
>>> where there is no realistic future need for such features, however, things
>>> could be simplified.
>>
>> Not only difficult - it would be virtually impossible to do it on a
>> system with virtual memory.  After all, page fault is an interrupt.  And
>> you don't need symmetric multiprocessing to cause a problem - even
>> hyper-threading can cause problems.
> 
> I would regard a hyper-threading system that treats virtual cores
> interchangeably as symmetric multiprocessing, as distinct from a system
> which assigns different cores (virtual or otherwise) to different hard-
> coded purposes.
> 

Not the same thing, and not necessarily symmetric multiprocessing.  SMP
was around long before hyper-threading.

> If most contested resources will only be used by a single core, that should
> greatly ease the amount of logic needed to synchronize access to those
> resources.  Resources that are shared between cores will need more complex
> logic, but being able to simplify most of the logic is better than not being
> able to simplify any.
> 

There is no guarantee that any single core will handle any resource - or
even that the same core will handle a resource at different times.

>> Only true if you're not multithreading.  But you're also assuming
>> specific machine cycles for each of these.  That makes your code even
>> more fragile.  What happens, for instance, when a new processor comes
>> out and you need three cycles per load or store?  Or someone takes your
>> code and puts it in a multi-threaded system?  Or one with virtual
>> memory?  Now it's even more fragile than before.
> 
> There are a variety of ways such things could be handled, e.g. by
> specifying the amount by which the "IRQ suspended" counter will be
> decremented after each particular instruction (possibly 1 for each
> instruction, or maybe more for "expensive" instructions).
> 

Or, you can just use mutex semaphores, which is what they are designed for.

> Besides, it's no different from any other decision to use a hardware feature
> that is available on some platforms and not others.  Code which is moved
> to a platform that doesn't support the feature will need to be reworked.
> 

Which only leads to more bugs.  Moving to a different chip does not
necessarily mean reworking any *good* program.  For instance, I can
build an application on Linux and run it on any of the current Intel
chips.  And, in fact, if I built an application on a Pentium, it would
probably still work on the current system, as long as I didn't use any
deprecated Linux features in the application.

>> A much better way is to just lock a mutex before you start, and unlock
>> it after you're done.  And each access to the protected area is guarded
>> by the same mutex.  It's not hard, and it's not very time consuming.
> 
> And what do you do if an interrupt handler needs something whose mutex is
> busy?
> 

You handle it like you do in any interrupt when the mutex is busy.  You
wait for the mutex to clear.  Before you attempt to lock the mutex, you
re-enable interrupts.  But a good interrupt handler will re-enable them
as soon as possible, anyway.

>> If you're updating something that can also be updated by an interrupt,
>> chances are you're already in supervisor mode to even access that
>> memory.  That's how the small embedded systems work.  And in that case,
>> a mutex is generally less than 5 or so instructions to lock or unlock -
>> which can be placed in a macro.
> 
> That isn't necessarily true.  It's not uncommon for interrupt handlers
> to use buffers and other data structures that can be placed anywhere in
> memory.  The pointers that say where those things go may be accessible
> only in supervisor mode, but the objects themselves may be wherever the
> client code wants them.
> 

Not really.  The buffers need to be in fixed physical memory, which is
going to be in kernel space.  But no matter where they are, if the
pointers are only accessible in supervisor mode, then the application
must also be running in supervisor mode.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92980

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-31 11:24 +0200
Message-ID<nq67o9$p9r$1@dont-email.me>
In reply to#92963
On 30/08/16 23:19, Jerry Stuckle wrote:
> On 8/30/2016 3:48 PM, supercat@casperkitty.com wrote:
>> On Tuesday, August 30, 2016 at 1:44:42 PM UTC-5, Jerry Stuckle wrote:
>>> And once again, if it takes more than (x) cycles to process, you need to
>>> disable interrupts twice.  And you can't allow interrupts to proceed
>>> between the two calls, because your update is no longer atomic.  But to
>>> not allow interrupts between successive calls means a bad application
>>> can lock the system.
>>
>> The purpose of the construct would be allow user-mode code to perform
>> certain kinds of simple atomic updates which are presently awkward.  If
>> an interrupt that might want to use a resource cannot be blocked while
>> the resource is being updated, it will be necessary to have the interrupt
>> return control to the mainline code without having used the resource but
>> somehow acquire control once the mainline code is done with it.
>>
> 
> But once again - user mode does not generally access the same buffers as
> interrupts - they operate in supervisor (kernel) mode.  If the
> application accesses the buffer, it will almost always be in supervisor
> mode.

Once again, you are thinking about a different sort of system from Supercat.

> 
> And in either user or supervisor mode, a mutex will block the interrupt
> thread from updating it, but on release of the mutex, the interrupt
> thread will be allowed to continue.
> 

Interrupts don't run threads.  They don't block on mutexes.  Interrupt
functions are called in response to a trigger - usually asynchronous,
such as external hardware asking for a response.  This is why they are
called "interrupts".

Normal execution of the main code (whichever thread) is suspended, the
interrupt function is run to completion (unless a nested interrupt hits
it), then you typically return directly to the main code that was
running before the interrupt.  The alternative is to trigger a thread swap.

An interrupt function must not block.  So it cannot use a normal
blocking mutex - it can take one if it is unlocked, but can't block
until it is ready.  So if the main code task has taken the mutex, the
interrupt can see that but it cannot wait for the mutex to become free -
it must be prepared to deal with the situation of a locked mutex.

> So there is no real problem.
> 
>>> And there are easy ways around the problem already.  They're called
>>> mutex semaphores.
>>
>> They work much well with threads, but poorly with interrupts.  If the
>> mainline uses locks when e.g. adding something to a linked list and an
>> interrupt needs to make use of that list, there won't be much the interrupt
>> handler can do if it is invoked while the list is locked.  The best it may
>> be able to do would be to set up some other interrupt handler to finish
>> the job once the list is unlocked, but that's nowhere near as practical as
>> delaying the invocation of the interrupt until the list is ready.  The
>> question is whether user-mode code should be able to handle simple update
>> cases without a context switch to supervisor mode.
>>
> 
> They work quite well with interrupts.  Of course the interrupt handler
> will not be able to update the list - but it can be designed so that
> it's not a problem.

Your way to deal with problems is to design the code so that it is not a
problem, therefore there is no problem.  Fantastic!

> 
> And once again - the interrupt handler is running in supervisor mode,
> accessing physical memory.  If there is a user application accessing the
> same memory, it is going to be running in supervisor mode, also - not
> user mode.
> 
>>>> One should not expect all features to be useful for all applications.
>>>> There are many cases where the only interrupts that could not be disabled
>>>> are those from things like bus errors, and where all such interrupts are
>>>> allowed to severely disrupt the execution state (e.g. where the system is
>>>> going to be restarted or shut down).
>>>
>>> In this case, you need to consider ALL - because ALL chips have
>>> non-maskable interrupts.  Bus errors and the like are not the only
>>> reasons for this happening.
>>
>> Some chips don't have any non-maskable interrupts, and many designs for
>> chips that do have NMI inputs have them permanently strapped inactive.
>> Otherwise, if a chip is going to save a 32-bits processor status word
>> where most bits are unused, using four (or so) otherwise-unused bits to
>> report whether and for low long low-priority interrupts were disabled
>> would take care of the issue provided the NMI didn't need to use the
>> contended resource.
>>
> 
> I don't know of any chips which don't have NMIs, or any *good* designs
> which strap them inactive.  I admit I don't know all chips or all
> designs - but there are valid reasons for having the NMIs - like an
> emergency reset of the system.

Most small microcontrollers do not have NMI's.

Most embedded systems do not use NMI's even though bigger
microcontrollers usually provide them.

NMI's are mostly used to indicate critical and irresolvable errors -
they are a signal from external hardware to say that the system is dying
/now/, and it's time for your final words.  Common examples are
uncorrectable errors from a memory system, or power fail interrupts.
Common responses are saving critical data to non-volatile memory,
setting an alarm, controlled shutdown of outputs, displaying a BSOD or
kernel panic, restarting the system, etc.  You don't normally return
from an NMI interrupt.  (The exception is that NMI's are sometimes used
by debugging systems - at the debugger code should of course not mess
with anything in the app or kernel.)

The ability to disable all normal interrupts is important to
implementing low-level synchronisation.  Interrupts that cannot be
disabled make this difficult or impossible.  At the very least, you have
to make sure that your NMI interrupts don't interact with other code in
a way that breaks the synchronisation - you can't work directly with
locks or atomic data that other code uses without very special care.

The way most microcontrollers handle this is to have a number of
interrupt levels, so that you can have high priority interrupts while
still having the ability to disable them when absolutely necessary.

> 
>>> And it still doesn't solve the problem in a multi-threaded system.
>>
>> If only a single core is used to access the contended resource, and if
>> disabling interrupts also disables context switching, what problem would
>> remain?  The approach wouldn't work very well in fancier systems, but on
>> the flip side fancier systems already have other ways to accomplish the
>> same purposes.  The design would offer the most benefit in systems that
>> would not otherwise need pre-emptive threading.
>>
> 
> You need to read up on hyper-threading.

I think he understands hyper-threading (or symmetric multi-threading, or
virtual cores, or whatever term the cpu manufacturer chooses to use).
Logically, it's just like multiple SMP cores.

> 
>>>> In designing a system it would likely be necessary to decide in advance
>>>> whether it will ever need virtual memory or symmetric multiprocessing,
>>>> since use of a short-term interrupt-disable feature would make it more
>>>> difficult to adapt the system to use either of those things.  In cases
>>>> where there is no realistic future need for such features, however, things
>>>> could be simplified.
>>>
>>> Not only difficult - it would be virtually impossible to do it on a
>>> system with virtual memory.  After all, page fault is an interrupt.  And
>>> you don't need symmetric multiprocessing to cause a problem - even
>>> hyper-threading can cause problems.
>>
>> I would regard a hyper-threading system that treats virtual cores
>> interchangeably as symmetric multiprocessing, as distinct from a system
>> which assigns different cores (virtual or otherwise) to different hard-
>> coded purposes.
>>
> 
> Not the same thing, and not necessarily symmetric multiprocessing.  SMP
> was around long before hyper-threading.

From the programmer's viewpoint, SMP and hyper-threading are the same
thing (other than speed, of course).

> 
>> If most contested resources will only be used by a single core, that should
>> greatly ease the amount of logic needed to synchronize access to those
>> resources.  Resources that are shared between cores will need more complex
>> logic, but being able to simplify most of the logic is better than not being
>> able to simplify any.
>>
> 
> There is no guarantee that any single core will handle any resource - or
> even that the same core will handle a resource at different times.

Read up about IRQ pinning.  It is not often used, but it is possible.

> 
>>> Only true if you're not multithreading.  But you're also assuming
>>> specific machine cycles for each of these.  That makes your code even
>>> more fragile.  What happens, for instance, when a new processor comes
>>> out and you need three cycles per load or store?  Or someone takes your
>>> code and puts it in a multi-threaded system?  Or one with virtual
>>> memory?  Now it's even more fragile than before.
>>
>> There are a variety of ways such things could be handled, e.g. by
>> specifying the amount by which the "IRQ suspended" counter will be
>> decremented after each particular instruction (possibly 1 for each
>> instruction, or maybe more for "expensive" instructions).
>>
> 
> Or, you can just use mutex semaphores, which is what they are designed for.
> 
>> Besides, it's no different from any other decision to use a hardware feature
>> that is available on some platforms and not others.  Code which is moved
>> to a platform that doesn't support the feature will need to be reworked.
>>
> 
> Which only leads to more bugs.  Moving to a different chip does not
> necessarily mean reworking any *good* program.  For instance, I can
> build an application on Linux and run it on any of the current Intel
> chips.  And, in fact, if I built an application on a Pentium, it would
> probably still work on the current system, as long as I didn't use any
> deprecated Linux features in the application.

This is called "hardware abstraction", and is one of the reasons why you
build your application on Linux rather than on bare metal.  The bits
that handle interrupts are usually very low level, and they are the bits
that may need changed for different hardware.

In this case, you might be using the temporary interrupt disable
function to implement C11 atomic access primitives, or equivalent
functions and macros.  The implementation details of these must be
changed for different hardware, but the code that uses them is portable.

> 
>>> A much better way is to just lock a mutex before you start, and unlock
>>> it after you're done.  And each access to the protected area is guarded
>>> by the same mutex.  It's not hard, and it's not very time consuming.
>>
>> And what do you do if an interrupt handler needs something whose mutex is
>> busy?
>>
> 
> You handle it like you do in any interrupt when the mutex is busy.  You
> wait for the mutex to clear.  Before you attempt to lock the mutex, you
> re-enable interrupts.  But a good interrupt handler will re-enable them
> as soon as possible, anyway.

You have a seriously bizarre idea about "good" code - and about
interrupt handlers.  Sometimes it's hard to know where to begin with
correcting the stuff you write.

> 
>>> If you're updating something that can also be updated by an interrupt,
>>> chances are you're already in supervisor mode to even access that
>>> memory.  That's how the small embedded systems work.  And in that case,
>>> a mutex is generally less than 5 or so instructions to lock or unlock -
>>> which can be placed in a macro.
>>
>> That isn't necessarily true.  It's not uncommon for interrupt handlers
>> to use buffers and other data structures that can be placed anywhere in
>> memory.  The pointers that say where those things go may be accessible
>> only in supervisor mode, but the objects themselves may be wherever the
>> client code wants them.
>>
> 
> Not really.  The buffers need to be in fixed physical memory, which is
> going to be in kernel space.  But no matter where they are, if the
> pointers are only accessible in supervisor mode, then the application
> must also be running in supervisor mode.
> 

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


#92989

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-31 10:33 -0400
Message-ID<nq6ps6$ksh$1@jstuckle.eternal-september.org>
In reply to#92980
On 8/31/2016 5:24 AM, David Brown wrote:
> On 30/08/16 23:19, Jerry Stuckle wrote:
>> On 8/30/2016 3:48 PM, supercat@casperkitty.com wrote:
>>> On Tuesday, August 30, 2016 at 1:44:42 PM UTC-5, Jerry Stuckle wrote:
>>>> And once again, if it takes more than (x) cycles to process, you need to
>>>> disable interrupts twice.  And you can't allow interrupts to proceed
>>>> between the two calls, because your update is no longer atomic.  But to
>>>> not allow interrupts between successive calls means a bad application
>>>> can lock the system.
>>>
>>> The purpose of the construct would be allow user-mode code to perform
>>> certain kinds of simple atomic updates which are presently awkward.  If
>>> an interrupt that might want to use a resource cannot be blocked while
>>> the resource is being updated, it will be necessary to have the interrupt
>>> return control to the mainline code without having used the resource but
>>> somehow acquire control once the mainline code is done with it.
>>>
>>
>> But once again - user mode does not generally access the same buffers as
>> interrupts - they operate in supervisor (kernel) mode.  If the
>> application accesses the buffer, it will almost always be in supervisor
>> mode.
> 
> Once again, you are thinking about a different sort of system from Supercat.
>

I'm thinking of what's in the real world. I don't know what you and
supercat are thinking of.

>>
>> And in either user or supervisor mode, a mutex will block the interrupt
>> thread from updating it, but on release of the mutex, the interrupt
>> thread will be allowed to continue.
>>
> 
> Interrupts don't run threads.  They don't block on mutexes.  Interrupt
> functions are called in response to a trigger - usually asynchronous,
> such as external hardware asking for a response.  This is why they are
> called "interrupts".
> 
> Normal execution of the main code (whichever thread) is suspended, the
> interrupt function is run to completion (unless a nested interrupt hits
> it), then you typically return directly to the main code that was
> running before the interrupt.  The alternative is to trigger a thread swap.
> 
> An interrupt function must not block.  So it cannot use a normal
> blocking mutex - it can take one if it is unlocked, but can't block
> until it is ready.  So if the main code task has taken the mutex, the
> interrupt can see that but it cannot wait for the mutex to become free -
> it must be prepared to deal with the situation of a locked mutex.
> 

The way it works, it can be considered a thread which runs to completion.

You are correct - an interrupt function must not block *in a single
thread system*.  It can block in a multi-thread system, if interrupts
are re-enabled before the block.  Not a good idea, but it can be done.

>> So there is no real problem.
>>
>>>> And there are easy ways around the problem already.  They're called
>>>> mutex semaphores.
>>>
>>> They work much well with threads, but poorly with interrupts.  If the
>>> mainline uses locks when e.g. adding something to a linked list and an
>>> interrupt needs to make use of that list, there won't be much the interrupt
>>> handler can do if it is invoked while the list is locked.  The best it may
>>> be able to do would be to set up some other interrupt handler to finish
>>> the job once the list is unlocked, but that's nowhere near as practical as
>>> delaying the invocation of the interrupt until the list is ready.  The
>>> question is whether user-mode code should be able to handle simple update
>>> cases without a context switch to supervisor mode.
>>>
>>
>> They work quite well with interrupts.  Of course the interrupt handler
>> will not be able to update the list - but it can be designed so that
>> it's not a problem.
> 
> Your way to deal with problems is to design the code so that it is not a
> problem, therefore there is no problem.  Fantastic!
> 

That is correct.  Design the code correctly, and it is not a problem.
Do not design the code correctly, and you have a problem.

Yes - Fantastic!

>>
>> And once again - the interrupt handler is running in supervisor mode,
>> accessing physical memory.  If there is a user application accessing the
>> same memory, it is going to be running in supervisor mode, also - not
>> user mode.
>>
>>>>> One should not expect all features to be useful for all applications.
>>>>> There are many cases where the only interrupts that could not be disabled
>>>>> are those from things like bus errors, and where all such interrupts are
>>>>> allowed to severely disrupt the execution state (e.g. where the system is
>>>>> going to be restarted or shut down).
>>>>
>>>> In this case, you need to consider ALL - because ALL chips have
>>>> non-maskable interrupts.  Bus errors and the like are not the only
>>>> reasons for this happening.
>>>
>>> Some chips don't have any non-maskable interrupts, and many designs for
>>> chips that do have NMI inputs have them permanently strapped inactive.
>>> Otherwise, if a chip is going to save a 32-bits processor status word
>>> where most bits are unused, using four (or so) otherwise-unused bits to
>>> report whether and for low long low-priority interrupts were disabled
>>> would take care of the issue provided the NMI didn't need to use the
>>> contended resource.
>>>
>>
>> I don't know of any chips which don't have NMIs, or any *good* designs
>> which strap them inactive.  I admit I don't know all chips or all
>> designs - but there are valid reasons for having the NMIs - like an
>> emergency reset of the system.
> 
> Most small microcontrollers do not have NMI's.
>

And those microcontrollers don't have kernel vs. user modes, so the
application can directly disable and re-enable interrupts.

> Most embedded systems do not use NMI's even though bigger
> microcontrollers usually provide them.
> 

Your proof?  All of the ones I've seen do.

> NMI's are mostly used to indicate critical and irresolvable errors -
> they are a signal from external hardware to say that the system is dying
> /now/, and it's time for your final words.  Common examples are
> uncorrectable errors from a memory system, or power fail interrupts.
> Common responses are saving critical data to non-volatile memory,
> setting an alarm, controlled shutdown of outputs, displaying a BSOD or
> kernel panic, restarting the system, etc.  You don't normally return
> from an NMI interrupt.  (The exception is that NMI's are sometimes used
> by debugging systems - at the debugger code should of course not mess
> with anything in the app or kernel.)
> 

That is one use.  They are also used where an interrupt is so critical
it must be handled immediately.  Real-time systems are one example.
Another one is life-safety.  In neither case do you have an error or the
system is dying.

> The ability to disable all normal interrupts is important to
> implementing low-level synchronisation.  Interrupts that cannot be
> disabled make this difficult or impossible.  At the very least, you have
> to make sure that your NMI interrupts don't interact with other code in
> a way that breaks the synchronisation - you can't work directly with
> locks or atomic data that other code uses without very special care.
> 
> The way most microcontrollers handle this is to have a number of
> interrupt levels, so that you can have high priority interrupts while
> still having the ability to disable them when absolutely necessary.
> 

Yes, and as I indicated before, applications in those microcontrollers
can directly disable and enable interrupts.

>>
>>>> And it still doesn't solve the problem in a multi-threaded system.
>>>
>>> If only a single core is used to access the contended resource, and if
>>> disabling interrupts also disables context switching, what problem would
>>> remain?  The approach wouldn't work very well in fancier systems, but on
>>> the flip side fancier systems already have other ways to accomplish the
>>> same purposes.  The design would offer the most benefit in systems that
>>> would not otherwise need pre-emptive threading.
>>>
>>
>> You need to read up on hyper-threading.
> 
> I think he understands hyper-threading (or symmetric multi-threading, or
> virtual cores, or whatever term the cpu manufacturer chooses to use).
> Logically, it's just like multiple SMP cores.
> 

Then you don't understand hyper-threading.  It is not the same as
symmetric multi-threading or virtual cores, or just like multiple SMP cores.

>>
>>>>> In designing a system it would likely be necessary to decide in advance
>>>>> whether it will ever need virtual memory or symmetric multiprocessing,
>>>>> since use of a short-term interrupt-disable feature would make it more
>>>>> difficult to adapt the system to use either of those things.  In cases
>>>>> where there is no realistic future need for such features, however, things
>>>>> could be simplified.
>>>>
>>>> Not only difficult - it would be virtually impossible to do it on a
>>>> system with virtual memory.  After all, page fault is an interrupt.  And
>>>> you don't need symmetric multiprocessing to cause a problem - even
>>>> hyper-threading can cause problems.
>>>
>>> I would regard a hyper-threading system that treats virtual cores
>>> interchangeably as symmetric multiprocessing, as distinct from a system
>>> which assigns different cores (virtual or otherwise) to different hard-
>>> coded purposes.
>>>
>>
>> Not the same thing, and not necessarily symmetric multiprocessing.  SMP
>> was around long before hyper-threading.
> 
> From the programmer's viewpoint, SMP and hyper-threading are the same
> thing (other than speed, of course).
> 

At the application level, yes.  At low level, there is a huge difference.

>>
>>> If most contested resources will only be used by a single core, that should
>>> greatly ease the amount of logic needed to synchronize access to those
>>> resources.  Resources that are shared between cores will need more complex
>>> logic, but being able to simplify most of the logic is better than not being
>>> able to simplify any.
>>>
>>
>> There is no guarantee that any single core will handle any resource - or
>> even that the same core will handle a resource at different times.
> 
> Read up about IRQ pinning.  It is not often used, but it is possible.
>

Which is not supported by all processors.

>>
>>>> Only true if you're not multithreading.  But you're also assuming
>>>> specific machine cycles for each of these.  That makes your code even
>>>> more fragile.  What happens, for instance, when a new processor comes
>>>> out and you need three cycles per load or store?  Or someone takes your
>>>> code and puts it in a multi-threaded system?  Or one with virtual
>>>> memory?  Now it's even more fragile than before.
>>>
>>> There are a variety of ways such things could be handled, e.g. by
>>> specifying the amount by which the "IRQ suspended" counter will be
>>> decremented after each particular instruction (possibly 1 for each
>>> instruction, or maybe more for "expensive" instructions).
>>>
>>
>> Or, you can just use mutex semaphores, which is what they are designed for.
>>
>>> Besides, it's no different from any other decision to use a hardware feature
>>> that is available on some platforms and not others.  Code which is moved
>>> to a platform that doesn't support the feature will need to be reworked.
>>>
>>
>> Which only leads to more bugs.  Moving to a different chip does not
>> necessarily mean reworking any *good* program.  For instance, I can
>> build an application on Linux and run it on any of the current Intel
>> chips.  And, in fact, if I built an application on a Pentium, it would
>> probably still work on the current system, as long as I didn't use any
>> deprecated Linux features in the application.
> 
> This is called "hardware abstraction", and is one of the reasons why you
> build your application on Linux rather than on bare metal.  The bits
> that handle interrupts are usually very low level, and they are the bits
> that may need changed for different hardware.
> 
> In this case, you might be using the temporary interrupt disable
> function to implement C11 atomic access primitives, or equivalent
> functions and macros.  The implementation details of these must be
> changed for different hardware, but the code that uses them is portable.
> 

Gee, you know the words "hardware abstraction".  Good for you!  Now if
you only knew how to implement it.  Your example would potentially have
to be reworked for *every processor* it is used on.  And you would have
to rework it not just one place - but every place your code uses your
new instruction.

As opposed to simply disabling and re-enabling interrupts with current
instructions, which require no rework on processors with the same
instruction set.

>>
>>>> A much better way is to just lock a mutex before you start, and unlock
>>>> it after you're done.  And each access to the protected area is guarded
>>>> by the same mutex.  It's not hard, and it's not very time consuming.
>>>
>>> And what do you do if an interrupt handler needs something whose mutex is
>>> busy?
>>>
>>
>> You handle it like you do in any interrupt when the mutex is busy.  You
>> wait for the mutex to clear.  Before you attempt to lock the mutex, you
>> re-enable interrupts.  But a good interrupt handler will re-enable them
>> as soon as possible, anyway.
> 
> You have a seriously bizarre idea about "good" code - and about
> interrupt handlers.  Sometimes it's hard to know where to begin with
> correcting the stuff you write.
> 

Not at all.  I've been doing it in multithreading systems since OS/2 1.0
came out in the 80's (actually I was introduced to it earlier in
mainframe OS's - but never had the need to use it).

It can be done - iff you know how to do it correctly.

>>
>>>> If you're updating something that can also be updated by an interrupt,
>>>> chances are you're already in supervisor mode to even access that
>>>> memory.  That's how the small embedded systems work.  And in that case,
>>>> a mutex is generally less than 5 or so instructions to lock or unlock -
>>>> which can be placed in a macro.
>>>
>>> That isn't necessarily true.  It's not uncommon for interrupt handlers
>>> to use buffers and other data structures that can be placed anywhere in
>>> memory.  The pointers that say where those things go may be accessible
>>> only in supervisor mode, but the objects themselves may be wherever the
>>> client code wants them.
>>>
>>
>> Not really.  The buffers need to be in fixed physical memory, which is
>> going to be in kernel space.  But no matter where they are, if the
>> pointers are only accessible in supervisor mode, then the application
>> must also be running in supervisor mode.
>>
> 

Once again you are showing your ignorance of a majority of the real
world.  And you don't address the main points - rather attacking
concepts you obviously know nothing about.

But that's not surprising for you.  You've done it before, and you'll
keep doing it.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92996

Fromsupercat@casperkitty.com
Date2016-08-31 09:51 -0700
Message-ID<84947d1f-48dd-4242-9e19-869107171243@googlegroups.com>
In reply to#92989
On Wednesday, August 31, 2016 at 9:33:52 AM UTC-5, Jerry Stuckle wrote:
> On 8/31/2016 5:24 AM, David Brown wrote:
> > Most embedded systems do not use NMI's even though bigger
> > microcontrollers usually provide them.
> 
> Your proof?  All of the ones I've seen do.

While NMIs may be commonplace in some application fields, they are very
rare in others, so many engineers--myself included--have produced many
designs without them.  What evidence do you have that they are used
as often as you claim?

> That is one use.  They are also used where an interrupt is so critical
> it must be handled immediately.  Real-time systems are one example.
> Another one is life-safety.  In neither case do you have an error or the
> system is dying.

Such things are best handled by interrupts that have higher priority but
are nonetheless maskable.  Unless a system has ways of disabling an NMI
during certain critical phases of operation (e.g. just after reset, before
everything is configured), an NMI handler will generally need to test,
before doing anything else, whether the system is in a state where it
should run.  The time required to take care of that could easily exceed
the worst-case latency for a high-priority interrupt.

> Then you don't understand hyper-threading.  It is not the same as
> symmetric multi-threading or virtual cores, or just like multiple SMP cores.

My understanding is that hyper-threading behaves semantically like two
CPU cores which share the same cache space and whose combined performance
will generally be less twice than that of a single core (but whose hardware
cost is so much less than twice that of a single core as to yield a
price/performance win).

> > From the programmer's viewpoint, SMP and hyper-threading are the same
> > thing (other than speed, of course).
> 
> At the application level, yes.  At low level, there is a huge difference.

What differences would be relevant from a programmer's viewpoint?

> > Read up about IRQ pinning.  It is not often used, but it is possible.
> 
> Which is not supported by all processors.

Really?  It wouldn't be possible to have all but one of the cores disable
all interrupts associated with an I/O device, and using scheduling
algorithms that use that core for precisely those tasks that should be run
on it?

> Gee, you know the words "hardware abstraction".  Good for you!  Now if
> you only knew how to implement it.  Your example would potentially have
> to be reworked for *every processor* it is used on.  And you would have
> to rework it not just one place - but every place your code uses your
> new instruction.

Most likely, use of a temporary-interrupt-disable instruction would be
limited to a few functions for things like double-linked-list insertion.
On systems which don't provide such a facility, the functions can be
written in other less-efficient ways without affecting the calling code.

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


#93036

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-31 22:46 -0400
Message-ID<nq84qp$2jb$1@jstuckle.eternal-september.org>
In reply to#92996
On 8/31/2016 12:51 PM, supercat@casperkitty.com wrote:
> On Wednesday, August 31, 2016 at 9:33:52 AM UTC-5, Jerry Stuckle wrote:
>> On 8/31/2016 5:24 AM, David Brown wrote:
>>> Most embedded systems do not use NMI's even though bigger
>>> microcontrollers usually provide them.
>>
>> Your proof?  All of the ones I've seen do.
> 
> While NMIs may be commonplace in some application fields, they are very
> rare in others, so many engineers--myself included--have produced many
> designs without them.  What evidence do you have that they are used
> as often as you claim?
> 
>> That is one use.  They are also used where an interrupt is so critical
>> it must be handled immediately.  Real-time systems are one example.
>> Another one is life-safety.  In neither case do you have an error or the
>> system is dying.
> 
> Such things are best handled by interrupts that have higher priority but
> are nonetheless maskable.  Unless a system has ways of disabling an NMI
> during certain critical phases of operation (e.g. just after reset, before
> everything is configured), an NMI handler will generally need to test,
> before doing anything else, whether the system is in a state where it
> should run.  The time required to take care of that could easily exceed
> the worst-case latency for a high-priority interrupt.
> 
>> Then you don't understand hyper-threading.  It is not the same as
>> symmetric multi-threading or virtual cores, or just like multiple SMP cores.
> 
> My understanding is that hyper-threading behaves semantically like two
> CPU cores which share the same cache space and whose combined performance
> will generally be less twice than that of a single core (but whose hardware
> cost is so much less than twice that of a single core as to yield a
> price/performance win).
> 
>>> From the programmer's viewpoint, SMP and hyper-threading are the same
>>> thing (other than speed, of course).
>>
>> At the application level, yes.  At low level, there is a huge difference.
> 
> What differences would be relevant from a programmer's viewpoint?
> 
>>> Read up about IRQ pinning.  It is not often used, but it is possible.
>>
>> Which is not supported by all processors.
> 
> Really?  It wouldn't be possible to have all but one of the cores disable
> all interrupts associated with an I/O device, and using scheduling
> algorithms that use that core for precisely those tasks that should be run
> on it?
> 

Over 25 years of working with engineers - including RTOS and life-safety
systems.

>> Gee, you know the words "hardware abstraction".  Good for you!  Now if
>> you only knew how to implement it.  Your example would potentially have
>> to be reworked for *every processor* it is used on.  And you would have
>> to rework it not just one place - but every place your code uses your
>> new instruction.
> 
> Most likely, use of a temporary-interrupt-disable instruction would be
> limited to a few functions for things like double-linked-list insertion.
> On systems which don't provide such a facility, the functions can be
> written in other less-efficient ways without affecting the calling code.
> 

Maybe, maybe not.  But whatever it is limited to - the code would have
to be gone through in detail for every potential processor it could run
on.  Maintenance would be a nightmare and bugs rampant.

But once again - if you're accessing the same memory as an interrupt,
you'll be accessing physical memory (required for interrupt handling).
That means in virtually every current system you'll be running in kernel
(or supervisor) state, where you can disable and re-enable interrupts
directly.

And if you're running on a system which supports kernel and user modes,
and running in user mode, you won't be directly accessing physical memory.

So no problem.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92968

From"Chris M. Thomasson" <invalid@invalid.invalid>
Date2016-08-30 16:26 -0700
Message-ID<nq54ml$2t1$1@dont-email.me>
In reply to#92952
On 8/30/2016 10:34 AM, supercat@casperkitty.com wrote:
> On Tuesday, August 30, 2016 at 9:53:47 AM UTC-5, Jerry Stuckle wrote:
>> On 8/30/2016 9:24 AM, David Brown wrote:
>>> This is the way it is done on most small systems, and it often forms a
>>> key part of higher-level synchronisation mechanisms.  It can even be a
>>> more efficient mechanism on processors with compare-and-swap or
>>> load-store "reservation" instructions.
>>
>> Yes, which is how mutexes are locked in such systems.  It's pretty fast.
>
> LDREX/STREX is generally pretty fast for handling updates to a single object,
> but are a bit awkward for updates that need to hit two things at once.
> It's possible to leverage a 32-bit LDREX and memory barriers to atomically
> update a 64-bit value among threads, but it's pretty complicated.  Having
> a quick sequence to disable interrupts, update the counter, and re-enable
> interrupts would make things much easier.  Doubly-linked-list updates can
> be handled smoothly with LDREX/STREX if code that uses backward links always
> double-checks their validity, but being able to disable interrupts long
> enough to do an update would greatly simplify them.

You must be _very_careful_ when you use load-linked store-conditional 
(LL/SC). One needs to take the implementation dependent reservation 
granule into account, and layout the data-structures accordingly.

One could theoretically open themselves up to live-lock conditions if 
they did not take this into consideration when implementing certain 
lock-free algorithms on PPC. For instance, if the anchor of a lock-free 
LIFO was not the size of a cache-line and/or reservation granule, and 
was not aligned on a cache-line and/or reservation granule boundary you 
could get "false-sharing" on the anchor. False-sharing could break 
reservations on the anchor and adversely affect forward progress, and 
might cause live-lock like conditions...

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


#93183

Fromsupercat@casperkitty.com
Date2016-09-03 17:31 -0700
Message-ID<c28eb537-3fbe-4842-b3ca-6c6a884895e3@googlegroups.com>
In reply to#92968
On Tuesday, August 30, 2016 at 6:26:22 PM UTC-5, Chris M. Thomasson wrote:
> You must be _very_careful_ when you use load-linked store-conditional 
> (LL/SC). One needs to take the implementation dependent reservation 
> granule into account, and layout the data-structures accordingly.

I would only consider LDREX/STREX as having a useful probability of success
when they are used to synthesize fairly simple operations like atomic
increment, combined and-xor, or compare-and-store on a single address.  Some
systems may implement reliable behaviors beyond that, but I don't count on
it.

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


#98629

From"Chris M. Thomasson" <invalid@invalid.invalid>
Date2016-12-09 16:03 -0800
Message-ID<o2fgmf$fmm$1@dont-email.me>
In reply to#93183
On 9/3/2016 5:31 PM, supercat@casperkitty.com wrote:
> On Tuesday, August 30, 2016 at 6:26:22 PM UTC-5, Chris M. Thomasson wrote:
>> You must be _very_careful_ when you use load-linked store-conditional
>> (LL/SC). One needs to take the implementation dependent reservation
>> granule into account, and layout the data-structures accordingly.
>
> I would only consider LDREX/STREX as having a useful probability of success
> when they are used to synthesize fairly simple operations like atomic
> increment, combined and-xor, or compare-and-store on a single address.  Some
> systems may implement reliable behaviors beyond that, but I don't count on
> it.
>

Fair enough. However, I really do dislike the looping nature of 
LDREX/STREX for atomic ops like fetch-and-add. For instance, a simple 
LOCK XADD on Intel does it all, loopless wrt asm code, and works nicely.

IMVVHO, LL/SC is prone to live-lock like conditions under periods of 
heavy load scenarios because of the explicit loop that has to be 
written. XADD is handled in hardware and/or microcode. It has to be more 
efficient that an explicit software loop.

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


#92959

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-30 21:36 +0200
Message-ID<nq4n80$iv3$1@dont-email.me>
In reply to#92949
On 30/08/16 16:53, Jerry Stuckle wrote:
> On 8/30/2016 9:24 AM, David Brown wrote:
>> On 30/08/16 14:12, Jerry Stuckle wrote:
>>> On 8/30/2016 7:21 AM, David Brown wrote:
>>>> On 29/08/16 23:24, Jerry Stuckle wrote:
>>>>> On 8/29/2016 5:16 PM, supercat@casperkitty.com wrote:
>>>>>> On Monday, August 29, 2016 at 3:43:08 PM UTC-5, Jerry Stuckle wrote:
>>>>>>> If the instruction disables interrupts for 16 cycles, and it is issued
>>>>>>> every 15 cycles, by your definition the interrupts will never be
>>>>>>> processed.  Otherwise the system wouldn't fulfill your "disabled for 16
>>>>>>> cycles" requirement.
>>>>>>
>>>>>> Should I have been more explicit "disabled for 16 cycles, or sooner if
>>>>>> another instruction enables interrupts"?  I would have thought the latter
>>>>>> was implied.
>>>>>>
>>>>>
>>>>> Make up your mind.  But once again you change the rules in the middle of
>>>>> the game.
>>>>>
>>>>>>> It's one or the other.  Either it waits 16 cycles or it doesn't.  You
>>>>>>> can't have it both ways.
>>>>>>
>>>>>> Up to 16 cycles, or shorter if the code doesn't want/need the full 16.
>>>>>>
>>>>>
>>>>> See above.
>>>>>
>>>>>>>> Since one should not expect to be able to run an arbitrary piece of code
>>>>>>>> within a short 15-cycle window, there should be no concern about a
>>>>>>>> context which uses the instruction being nested within another context
>>>>>>>> that expects interrupts to be disabled continuously throughout it, since
>>>>>>>> whoever is writing the outer code should be aware of what's within it
>>>>>>>> (note that the construct would really only be useful from within assembly
>>>>>>>> code, or with a compiler mode that is documented as generating code in a
>>>>>>>> very straightforward and predictable fashion).
>>>>>>>>
>>>>>>>
>>>>>>> It doesn't need to run "an arbitrary piece of code".  It just needs to
>>>>>>> keep reissuing the instruction.
>>>>>>
>>>>>> And each time it issues it, the instruction starts by processing any
>>>>>> interrupts that have become pending since the last time the instruction
>>>>>> was issued.
>>>>>>
>>>>>
>>>>> And a solution to a problem which doesn't exist.  That's what semaphores
>>>>> are for.
>>>>>
>>>>> And *no one except the kernel* should be able to disable interrupts,
>>>>> even for a short period of time.  Even with your "rules" it can have a
>>>>> detrimental performance on the system.
>>>>>
>>>>>  From your updates, it's obvious you've never done any kernel programming
>>>>> in the past.  It is an entirely different approach than application
>>>>> programming.
>>>>>
>>>>
>>>> Actually, I think Supercat's idea here would have a great deal of
>>>> practical use, though it is primarily for single core systems (or as an
>>>> aid to making more general SMP locks and semaphores).  I have also
>>>> thought for years that it would be a very useful type of instruction,
>>>> especially for embedded systems (though I think 16 cycle disable is
>>>> longer than necessary).
>>>>
>>>> As usual, Jerry, you don't understand what is being suggested, and
>>>> therefore insult people rather than attempting to think or to
>>>> communicate like a normal person.  But let me try to re-phrase the idea,
>>>> and see if you understand it.
>>>>
>>>>
>>>> It is often important to be able to perform a sequence of operations in
>>>> an atomic fashion.  There are a variety of methods for doing this, such
>>>> as building primitives for locking from instructions such
>>>> "compare-and-swap" and "store-with-reservation", carefully ordered
>>>> memory accesses, or even special hardware to support semaphores.  All of
>>>> these have disadvantages - there can be significant overhead, and
>>>> perhaps trial-and-retry loops, which means that something as simple as
>>>> an atomic double-word read or write takes many times longer than the
>>>> non-atomic version.
>>>>
>>>> In single processor systems, the easiest and most efficient way to
>>>> handle this is often to disable interrupts temporarily, then restore
>>>> them after the atomic operation.  This is a cornerstone of embedded
>>>> programming, and on bigger systems (with a distinction between user
>>>> modes and privileged modes) it is often used in the kernel-side
>>>> implementation of the OS's locking mechanisms.
>>>>
>>>> But manually enabling and disabling interrupts can be error-prone.  It
>>>> can be difficult to ensure that the interrupt disabled time is minimised
>>>> (to avoid extra latency for interrupt routines), and user-mode code
>>>> generally cannot disable interrupts because the relevant instructions
>>>> are privileged.
>>>>
>>>> So the suggestion is for an instruction that will temporarily disable
>>>> interrupts for a given number of clock cycles or instruction counts,
>>>> after which they will automatically be restored to the previous state.
>>>> The hardware would guarantee that pending interrupts are run before a
>>>> new temporary interrupt disable instruction is run, thus ensuring that
>>>> interrupts can't be blocked for more than the maximum specified time.
>>>>
>>>> This would make atomic accesses and lock primitives very simple and
>>>> efficient, and eliminate much of the overhead needed when these are
>>>> handled from user-mode (at least in the common case when there is no
>>>> conflict).  For single cpu embedded systems, it would be a great feature.
>>>>
>>>> There would be complications, of course, such as how it would interact
>>>> with non-maskable interrupts or faults.  But such issues can be solved.
>>>>
>>>> For multi-cpu systems, it would be harder - ideally, the feature could
>>>> be combined with locking of a small address range.  A little more
>>>> thought would be needed in order to ensure that this would be fair, and
>>>> one process could not make a denial-of-service attack on another process
>>>> (at least, not in a worse way than it can today by grabbing locks).
>>>>
>>>
>>> I understand exactly what is being suggested, David.  And I still think
>>> it's a bad suggestion - open to all kinds of problems.
>>>
>>
>> It is not a golden bullet, and yes, there would be complications.  But
>> it would be another useful tool.
>>
>>> I've worked with a lot of good programmers on OS's and embedded systems
>>> over the years.  They haven't had problems with disabling and
>>> re-enabling interrupts - but then they don't normally have to do it very
>>> often.  About the only time it is important is when they have to update
>>> a data structure that is also used by an interrupt handler, and even
>>> then it's often better to use mutexes to handle the operation rather
>>> than disable all interrupts.  And yes, mutexes can be used in interrupt
>>> handlers.
>>
>> On a larger system with a bigger OS, perhaps multiple cores, and many
>> developers that need strict interfaces between different parts of the
>> code - then yes, mutexes or other higher level locking mechanisms are
>> often best.  (And I agree that some types of locks or mutexes can be
>> used in interrupts, as long as you have the right kind of locks and use
>> them in the right way.)
>>
>> But these mechanisms can quickly have much more overhead than a simple
>> "disable global interrupts, do the job, re-enable interrupt status".
>> For small job, such as atomically incrementing a counter, you could be
>> talking about hundreds of times larger overhead.
>>
>
> Not necessarily. Most systems have atomic operations for something like
> incrementing a counter.

Most RISC processors do not have any sort of atomic operation for 
incrementing a counter.  Most CISC processors do (as long as the counter 
is not too big).

>  After all, similar operations are used to
> create mutexes.  And even if not, mutexes locking and unlocking mutexes
> is a highly optimized operation in any OS I've seen - often as little as
> a half-dozen machine instructions or less, which can generally be
> implemented inline via a macro.

A half-dozen instructions, often including a loop, is far more than a 
single instruction.

But again, there is a difference between bigger and smaller systems. 
Small devices usually don't have operations optimised for mutexes, and 
interrupt disabling is the normal way to do atomic operations.  Bigger 
devices usually have some way to get fast mutexes or other locks, 
because you need a more sophisticated locking mechanism when dealing 
with multiple cores.

>
>> This is the way it is done on most small systems, and it often forms a
>> key part of higher-level synchronisation mechanisms.  It can even be a
>> more efficient mechanism on processors with compare-and-swap or
>> load-store "reservation" instructions.
>>
>
> Yes, which is how mutexes are locked in such systems.  It's pretty fast.
>
>>>
>>> And even then, it's not possible to disable all interrupts.  Most
>>> processors have non-maskable interrupts, which cannot be disabled.
>>> These are important for things like a hardware interrupt.
>>
>> In most cases on small systems, you /can/ disable almost all interrupts.
>>   Non-maskable interrupts are rarely used, except perhaps for extreme
>> situations (like power-fail interrupts).  Bigger systems may be more
>> complicated, of course.
>>
>
> "Almost" is not "all".  And they still have to be considered.  Failure
> to do things like this is a common cause of design bugs.
>

References?  Samples?  Examples?

>>>
>>> Another problem here is how you and supercat want it to work.  You want
>>> to disable it for 16 cycles.  That may not be enough, or it may be too
>>> long.  If it's not enough, then you have to reissue it by the time 15
>>> cycles have elapsed.  However, that leaves the system wide open to a
>>> rogue application shutting the system out by continuing to disable
>>> interrupts.  So you say "allow interrupts before disabling again".  But
>>> now that destroys your atomic operation - an interrupt handler can get
>>> in during that time and change things.
>>
>> I don't want to allow a restart of the counter before interrupts are
>> re-enabled - if you issue a new temporary interrupt disable counter
>> instruction before the previous one runs out, you get pending interrupts
>> at that point before the counter is restarted.  That is your protection
>> against unexpected interrupt latency.  The 16 cycles (which may be clock
>> cycles, or instruction counts) should be plenty of simple locking - and
>> if you need more, you use the simple locks to build your big locks, or
>> you go back to old-fashioned interrupt disable code.
>>
>
> Which then means your update is no longer atomic.  Something can get in
> in the middle and change things.  And 16 instruction cycles is more than
> it takes to lock and unlock a mutex in many systems.

I thought you said mutexes were so incredibly fast - now you think they 
are too slow.

Of course, on a single core system, once your interrupts are disabled it 
is a lot easier to make a fast mutex lock or unlock.  You can also do 
simple checking and setting of flag variables, because you know the 
process will not be interrupted half-way through.

>
>>>
>>> And as you mentioned - this would only work for single core and single
>>> thread systems.  Although there are still a lot of single-core,
>>> single-thread systems around, multi-core and multi-threaded processors
>>> are becoming more and more prevalent, even in embedded systems.
>>
>> It will be fine for multiple threads on the single core processor - it
>> is only when you have multiple cores or virtual cores that there is a
>> problem.  And while I agree that multi-core processors are becoming more
>> common in embedded systems, the /huge/ majority of embedded
>> microcontrollers are single core (or non-SMP multi-core, where you
>> effectively have two independent systems on the same chip).
>>
>
> Ah, but you can also have multithreading on a single core system, ala
> Intel's hyper-threading, which allows two virtual cores on one real core.

See a few lines earlier, when I wrote "multiple cores or virtual cores".

>
>>>
>>> No, it's a bad idea, and not required.  If the hardware manufacturers
>>> thought it was a good idea, someone would have implemented it by now.
>>> The fact no one has indicates they see the potential problems much
>>> better than you do, and understand it's a problem that already has good
>>> solutions.
>>>
>>
>> I agree it is not a required feature - after all, we got on fine without
>> it.  And there would be complications in implementing it in hardware, it
>> would not scale to multi-core systems, and it would be less useful and
>> more complicated with superscaler processors.  But for smaller systems
>> and simpler microcontrollers, it would definitely be a useful feature.
>> Whether or not it would be cost-effective (no feature is free) is
>> another matter.
>>
>
> I just see too many downsides to this and no real upside - other than
> not wanting to ensure you've enabled interrupts after disabling them.
>
> But then I almost never disable interrupts, even in kernel code (and
> never in application code).  It's just so rarely necessary.  If you find
> you are doing so regularly, you need to be looking at why.
>

You don't do the same sort of programming as me - just because an idea 
does not seem useful to /you/, does not mean it is not useful to others.

Having said that, it is not /that/ often that I disable interrupts 
either.  And I never forget to re-enable them appropriately.  But when I 
do disable interrupts, it is usually for a short time in a small piece 
of code, and an instruction that would make such sequences more 
efficient would be nice.  Not essential, and perhaps not worth the cost 
(that's up to chip designers to decide) - but nice.

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


#92964

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-08-30 17:30 -0400
Message-ID<nq4tuf$b2d$1@jstuckle.eternal-september.org>
In reply to#92959
On 8/30/2016 3:36 PM, David Brown wrote:
> On 30/08/16 16:53, Jerry Stuckle wrote:
>> On 8/30/2016 9:24 AM, David Brown wrote:
>>> On 30/08/16 14:12, Jerry Stuckle wrote:
>>>> On 8/30/2016 7:21 AM, David Brown wrote:
>>>>> On 29/08/16 23:24, Jerry Stuckle wrote:
>>>>>> On 8/29/2016 5:16 PM, supercat@casperkitty.com wrote:
>>>>>>> On Monday, August 29, 2016 at 3:43:08 PM UTC-5, Jerry Stuckle wrote:
>>>>>>>> If the instruction disables interrupts for 16 cycles, and it is
>>>>>>>> issued
>>>>>>>> every 15 cycles, by your definition the interrupts will never be
>>>>>>>> processed.  Otherwise the system wouldn't fulfill your "disabled
>>>>>>>> for 16
>>>>>>>> cycles" requirement.
>>>>>>>
>>>>>>> Should I have been more explicit "disabled for 16 cycles, or
>>>>>>> sooner if
>>>>>>> another instruction enables interrupts"?  I would have thought
>>>>>>> the latter
>>>>>>> was implied.
>>>>>>>
>>>>>>
>>>>>> Make up your mind.  But once again you change the rules in the
>>>>>> middle of
>>>>>> the game.
>>>>>>
>>>>>>>> It's one or the other.  Either it waits 16 cycles or it
>>>>>>>> doesn't.  You
>>>>>>>> can't have it both ways.
>>>>>>>
>>>>>>> Up to 16 cycles, or shorter if the code doesn't want/need the
>>>>>>> full 16.
>>>>>>>
>>>>>>
>>>>>> See above.
>>>>>>
>>>>>>>>> Since one should not expect to be able to run an arbitrary
>>>>>>>>> piece of code
>>>>>>>>> within a short 15-cycle window, there should be no concern about a
>>>>>>>>> context which uses the instruction being nested within another
>>>>>>>>> context
>>>>>>>>> that expects interrupts to be disabled continuously throughout
>>>>>>>>> it, since
>>>>>>>>> whoever is writing the outer code should be aware of what's
>>>>>>>>> within it
>>>>>>>>> (note that the construct would really only be useful from
>>>>>>>>> within assembly
>>>>>>>>> code, or with a compiler mode that is documented as generating
>>>>>>>>> code in a
>>>>>>>>> very straightforward and predictable fashion).
>>>>>>>>>
>>>>>>>>
>>>>>>>> It doesn't need to run "an arbitrary piece of code".  It just
>>>>>>>> needs to
>>>>>>>> keep reissuing the instruction.
>>>>>>>
>>>>>>> And each time it issues it, the instruction starts by processing any
>>>>>>> interrupts that have become pending since the last time the
>>>>>>> instruction
>>>>>>> was issued.
>>>>>>>
>>>>>>
>>>>>> And a solution to a problem which doesn't exist.  That's what
>>>>>> semaphores
>>>>>> are for.
>>>>>>
>>>>>> And *no one except the kernel* should be able to disable interrupts,
>>>>>> even for a short period of time.  Even with your "rules" it can
>>>>>> have a
>>>>>> detrimental performance on the system.
>>>>>>
>>>>>>  From your updates, it's obvious you've never done any kernel
>>>>>> programming
>>>>>> in the past.  It is an entirely different approach than application
>>>>>> programming.
>>>>>>
>>>>>
>>>>> Actually, I think Supercat's idea here would have a great deal of
>>>>> practical use, though it is primarily for single core systems (or
>>>>> as an
>>>>> aid to making more general SMP locks and semaphores).  I have also
>>>>> thought for years that it would be a very useful type of instruction,
>>>>> especially for embedded systems (though I think 16 cycle disable is
>>>>> longer than necessary).
>>>>>
>>>>> As usual, Jerry, you don't understand what is being suggested, and
>>>>> therefore insult people rather than attempting to think or to
>>>>> communicate like a normal person.  But let me try to re-phrase the
>>>>> idea,
>>>>> and see if you understand it.
>>>>>
>>>>>
>>>>> It is often important to be able to perform a sequence of
>>>>> operations in
>>>>> an atomic fashion.  There are a variety of methods for doing this,
>>>>> such
>>>>> as building primitives for locking from instructions such
>>>>> "compare-and-swap" and "store-with-reservation", carefully ordered
>>>>> memory accesses, or even special hardware to support semaphores. 
>>>>> All of
>>>>> these have disadvantages - there can be significant overhead, and
>>>>> perhaps trial-and-retry loops, which means that something as simple as
>>>>> an atomic double-word read or write takes many times longer than the
>>>>> non-atomic version.
>>>>>
>>>>> In single processor systems, the easiest and most efficient way to
>>>>> handle this is often to disable interrupts temporarily, then restore
>>>>> them after the atomic operation.  This is a cornerstone of embedded
>>>>> programming, and on bigger systems (with a distinction between user
>>>>> modes and privileged modes) it is often used in the kernel-side
>>>>> implementation of the OS's locking mechanisms.
>>>>>
>>>>> But manually enabling and disabling interrupts can be error-prone.  It
>>>>> can be difficult to ensure that the interrupt disabled time is
>>>>> minimised
>>>>> (to avoid extra latency for interrupt routines), and user-mode code
>>>>> generally cannot disable interrupts because the relevant instructions
>>>>> are privileged.
>>>>>
>>>>> So the suggestion is for an instruction that will temporarily disable
>>>>> interrupts for a given number of clock cycles or instruction counts,
>>>>> after which they will automatically be restored to the previous state.
>>>>> The hardware would guarantee that pending interrupts are run before a
>>>>> new temporary interrupt disable instruction is run, thus ensuring that
>>>>> interrupts can't be blocked for more than the maximum specified time.
>>>>>
>>>>> This would make atomic accesses and lock primitives very simple and
>>>>> efficient, and eliminate much of the overhead needed when these are
>>>>> handled from user-mode (at least in the common case when there is no
>>>>> conflict).  For single cpu embedded systems, it would be a great
>>>>> feature.
>>>>>
>>>>> There would be complications, of course, such as how it would interact
>>>>> with non-maskable interrupts or faults.  But such issues can be
>>>>> solved.
>>>>>
>>>>> For multi-cpu systems, it would be harder - ideally, the feature could
>>>>> be combined with locking of a small address range.  A little more
>>>>> thought would be needed in order to ensure that this would be fair,
>>>>> and
>>>>> one process could not make a denial-of-service attack on another
>>>>> process
>>>>> (at least, not in a worse way than it can today by grabbing locks).
>>>>>
>>>>
>>>> I understand exactly what is being suggested, David.  And I still think
>>>> it's a bad suggestion - open to all kinds of problems.
>>>>
>>>
>>> It is not a golden bullet, and yes, there would be complications.  But
>>> it would be another useful tool.
>>>
>>>> I've worked with a lot of good programmers on OS's and embedded systems
>>>> over the years.  They haven't had problems with disabling and
>>>> re-enabling interrupts - but then they don't normally have to do it
>>>> very
>>>> often.  About the only time it is important is when they have to update
>>>> a data structure that is also used by an interrupt handler, and even
>>>> then it's often better to use mutexes to handle the operation rather
>>>> than disable all interrupts.  And yes, mutexes can be used in interrupt
>>>> handlers.
>>>
>>> On a larger system with a bigger OS, perhaps multiple cores, and many
>>> developers that need strict interfaces between different parts of the
>>> code - then yes, mutexes or other higher level locking mechanisms are
>>> often best.  (And I agree that some types of locks or mutexes can be
>>> used in interrupts, as long as you have the right kind of locks and use
>>> them in the right way.)
>>>
>>> But these mechanisms can quickly have much more overhead than a simple
>>> "disable global interrupts, do the job, re-enable interrupt status".
>>> For small job, such as atomically incrementing a counter, you could be
>>> talking about hundreds of times larger overhead.
>>>
>>
>> Not necessarily. Most systems have atomic operations for something like
>> incrementing a counter.
> 
> Most RISC processors do not have any sort of atomic operation for
> incrementing a counter.  Most CISC processors do (as long as the counter
> is not too big).
> 

But any one which has support for multiple threads has some kind of
atomic operation.

>>  After all, similar operations are used to
>> create mutexes.  And even if not, mutexes locking and unlocking mutexes
>> is a highly optimized operation in any OS I've seen - often as little as
>> a half-dozen machine instructions or less, which can generally be
>> implemented inline via a macro.
> 
> A half-dozen instructions, often including a loop, is far more than a
> single instruction.
> 
> But again, there is a difference between bigger and smaller systems.
> Small devices usually don't have operations optimised for mutexes, and
> interrupt disabling is the normal way to do atomic operations.  Bigger
> devices usually have some way to get fast mutexes or other locks,
> because you need a more sophisticated locking mechanism when dealing
> with multiple cores.
> 

If you are talking about small systems, then they only run the
equivalent of kernel mode - no separation between kernel and user
instructions.  So it's quite easy to disable interrupts then re-enable
them.  Two instructions, typically.

>>
>>> This is the way it is done on most small systems, and it often forms a
>>> key part of higher-level synchronisation mechanisms.  It can even be a
>>> more efficient mechanism on processors with compare-and-swap or
>>> load-store "reservation" instructions.
>>>
>>
>> Yes, which is how mutexes are locked in such systems.  It's pretty fast.
>>
>>>>
>>>> And even then, it's not possible to disable all interrupts.  Most
>>>> processors have non-maskable interrupts, which cannot be disabled.
>>>> These are important for things like a hardware interrupt.
>>>
>>> In most cases on small systems, you /can/ disable almost all interrupts.
>>>   Non-maskable interrupts are rarely used, except perhaps for extreme
>>> situations (like power-fail interrupts).  Bigger systems may be more
>>> complicated, of course.
>>>
>>
>> "Almost" is not "all".  And they still have to be considered.  Failure
>> to do things like this is a common cause of design bugs.
>>
> 
> References?  Samples?  Examples?
> 

Non-maskable interrupt can never be disabled.  See documentation on
Intel and other chips.

And you have to know what the interrupt handler will do when it gets the
interrupt.  It may not just reboot the system, for instance.  Back in
the MS-DOS days, I had a debugger with a card that had a button on it.
Pressing the button generated a NMI which normally would have rebooted
the computer.  But the code they put in brought up a system debugger
instead.

>>>>
>>>> Another problem here is how you and supercat want it to work.  You want
>>>> to disable it for 16 cycles.  That may not be enough, or it may be too
>>>> long.  If it's not enough, then you have to reissue it by the time 15
>>>> cycles have elapsed.  However, that leaves the system wide open to a
>>>> rogue application shutting the system out by continuing to disable
>>>> interrupts.  So you say "allow interrupts before disabling again".  But
>>>> now that destroys your atomic operation - an interrupt handler can get
>>>> in during that time and change things.
>>>
>>> I don't want to allow a restart of the counter before interrupts are
>>> re-enabled - if you issue a new temporary interrupt disable counter
>>> instruction before the previous one runs out, you get pending interrupts
>>> at that point before the counter is restarted.  That is your protection
>>> against unexpected interrupt latency.  The 16 cycles (which may be clock
>>> cycles, or instruction counts) should be plenty of simple locking - and
>>> if you need more, you use the simple locks to build your big locks, or
>>> you go back to old-fashioned interrupt disable code.
>>>
>>
>> Which then means your update is no longer atomic.  Something can get in
>> in the middle and change things.  And 16 instruction cycles is more than
>> it takes to lock and unlock a mutex in many systems.
> 
> I thought you said mutexes were so incredibly fast - now you think they
> are too slow.
> 

Read again.  I said just the opposite.

> Of course, on a single core system, once your interrupts are disabled it
> is a lot easier to make a fast mutex lock or unlock.  You can also do
> simple checking and setting of flag variables, because you know the
> process will not be interrupted half-way through.
> 

*Maybe*.

>>
>>>>
>>>> And as you mentioned - this would only work for single core and single
>>>> thread systems.  Although there are still a lot of single-core,
>>>> single-thread systems around, multi-core and multi-threaded processors
>>>> are becoming more and more prevalent, even in embedded systems.
>>>
>>> It will be fine for multiple threads on the single core processor - it
>>> is only when you have multiple cores or virtual cores that there is a
>>> problem.  And while I agree that multi-core processors are becoming more
>>> common in embedded systems, the /huge/ majority of embedded
>>> microcontrollers are single core (or non-SMP multi-core, where you
>>> effectively have two independent systems on the same chip).
>>>
>>
>> Ah, but you can also have multithreading on a single core system, ala
>> Intel's hyper-threading, which allows two virtual cores on one real core.
> 
> See a few lines earlier, when I wrote "multiple cores or virtual cores".
> 

Yes, I know what you said.

>>
>>>>
>>>> No, it's a bad idea, and not required.  If the hardware manufacturers
>>>> thought it was a good idea, someone would have implemented it by now.
>>>> The fact no one has indicates they see the potential problems much
>>>> better than you do, and understand it's a problem that already has good
>>>> solutions.
>>>>
>>>
>>> I agree it is not a required feature - after all, we got on fine without
>>> it.  And there would be complications in implementing it in hardware, it
>>> would not scale to multi-core systems, and it would be less useful and
>>> more complicated with superscaler processors.  But for smaller systems
>>> and simpler microcontrollers, it would definitely be a useful feature.
>>> Whether or not it would be cost-effective (no feature is free) is
>>> another matter.
>>>
>>
>> I just see too many downsides to this and no real upside - other than
>> not wanting to ensure you've enabled interrupts after disabling them.
>>
>> But then I almost never disable interrupts, even in kernel code (and
>> never in application code).  It's just so rarely necessary.  If you find
>> you are doing so regularly, you need to be looking at why.
>>
> 
> You don't do the same sort of programming as me - just because an idea
> does not seem useful to /you/, does not mean it is not useful to others.
> 

I wouldn't say that.  I have worked on some pretty small chips - ones
that can't even be programmed in C - you have to use assembler.

And I still don't see a reason for the idea, when there are already good
ways to do it.

And obviously the chip manufacturers agree, because *none* of them have
implemented it.  If someone thought it was a good idea, it would be part
of their instruction set.

> Having said that, it is not /that/ often that I disable interrupts
> either.  And I never forget to re-enable them appropriately.  But when I
> do disable interrupts, it is usually for a short time in a small piece
> of code, and an instruction that would make such sequences more
> efficient would be nice.  Not essential, and perhaps not worth the cost
> (that's up to chip designers to decide) - but nice.
> 
> 

Exactly - how it should be done.  And if you have such a small system,
then you're already in kernel mode, so you have two instructions  - one
to disable interrupts, and a second to enable them.  No problem.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

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


#92982

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-31 12:39 +0200
Message-ID<nq6c4e$6rd$1@dont-email.me>
In reply to#92964
On 30/08/16 23:30, Jerry Stuckle wrote:
> On 8/30/2016 3:36 PM, David Brown wrote:
>> On 30/08/16 16:53, Jerry Stuckle wrote:
>>> On 8/30/2016 9:24 AM, David Brown wrote:
>>>> On 30/08/16 14:12, Jerry Stuckle wrote:
>>>>> On 8/30/2016 7:21 AM, David Brown wrote:

<snip>

>>>> But these mechanisms can quickly have much more overhead than a simple
>>>> "disable global interrupts, do the job, re-enable interrupt status".
>>>> For small job, such as atomically incrementing a counter, you could be
>>>> talking about hundreds of times larger overhead.
>>>>
>>>
>>> Not necessarily. Most systems have atomic operations for something like
>>> incrementing a counter.
>>
>> Most RISC processors do not have any sort of atomic operation for
>> incrementing a counter.  Most CISC processors do (as long as the counter
>> is not too big).
>>
> 
> But any one which has support for multiple threads has some kind of
> atomic operation.

Yes, but in most cases (Alpha, PPC, MIPS, ARM - and probably many others
that I don't know) this is using a load-link or load-reserve and
conditional store mechanism.  There is no atomic operation for counter
incrementing - they have no mechanism for a single read-modify-write
operation.  Rather, you use the LL and SC instructions to make a
sequence of operations atomic.  And since the final SC can fail, you
need a conditional loop.

> 
>>>  After all, similar operations are used to
>>> create mutexes.  And even if not, mutexes locking and unlocking mutexes
>>> is a highly optimized operation in any OS I've seen - often as little as
>>> a half-dozen machine instructions or less, which can generally be
>>> implemented inline via a macro.
>>
>> A half-dozen instructions, often including a loop, is far more than a
>> single instruction.
>>
>> But again, there is a difference between bigger and smaller systems.
>> Small devices usually don't have operations optimised for mutexes, and
>> interrupt disabling is the normal way to do atomic operations.  Bigger
>> devices usually have some way to get fast mutexes or other locks,
>> because you need a more sophisticated locking mechanism when dealing
>> with multiple cores.
>>
> 
> If you are talking about small systems, then they only run the
> equivalent of kernel mode - no separation between kernel and user
> instructions.  So it's quite easy to disable interrupts then re-enable
> them.  Two instructions, typically.

More than that if you want to support restoring interrupt status rather
than enabling interrupts, or if you want to handle multiple priority levels.

> 
>>>
>>>> This is the way it is done on most small systems, and it often forms a
>>>> key part of higher-level synchronisation mechanisms.  It can even be a
>>>> more efficient mechanism on processors with compare-and-swap or
>>>> load-store "reservation" instructions.
>>>>
>>>
>>> Yes, which is how mutexes are locked in such systems.  It's pretty fast.
>>>
>>>>>
>>>>> And even then, it's not possible to disable all interrupts.  Most
>>>>> processors have non-maskable interrupts, which cannot be disabled.
>>>>> These are important for things like a hardware interrupt.
>>>>
>>>> In most cases on small systems, you /can/ disable almost all interrupts.
>>>>   Non-maskable interrupts are rarely used, except perhaps for extreme
>>>> situations (like power-fail interrupts).  Bigger systems may be more
>>>> complicated, of course.
>>>>
>>>
>>> "Almost" is not "all".  And they still have to be considered.  Failure
>>> to do things like this is a common cause of design bugs.
>>>
>>
>> References?  Samples?  Examples?
>>
> 
> Non-maskable interrupt can never be disabled.  See documentation on
> Intel and other chips.

No one said you could disable NMI's - the name "non-maskable" is a clue
here.  What has been said is that NMI's are rarely used - you don't
disable them, you simply don't activate them.

> 
> And you have to know what the interrupt handler will do when it gets the
> interrupt.  It may not just reboot the system, for instance.  Back in
> the MS-DOS days, I had a debugger with a card that had a button on it.
> Pressing the button generated a NMI which normally would have rebooted
> the computer.  But the code they put in brought up a system debugger
> instead.
> 

I am still waiting for references to justify why NMI's have to be
considered (rather than simply not used), and why failure to consider
them is a "common cause of design bugs".  You might also like to explain
why they "are important for things like a hardware interrupt" when
hardware interrupts almost invariably use /maskable/ interrupts.

<snip>

>>>
>>>>>
>>>>> No, it's a bad idea, and not required.  If the hardware manufacturers
>>>>> thought it was a good idea, someone would have implemented it by now.
>>>>> The fact no one has indicates they see the potential problems much
>>>>> better than you do, and understand it's a problem that already has good
>>>>> solutions.
>>>>>
>>>>
>>>> I agree it is not a required feature - after all, we got on fine without
>>>> it.  And there would be complications in implementing it in hardware, it
>>>> would not scale to multi-core systems, and it would be less useful and
>>>> more complicated with superscaler processors.  But for smaller systems
>>>> and simpler microcontrollers, it would definitely be a useful feature.
>>>> Whether or not it would be cost-effective (no feature is free) is
>>>> another matter.
>>>>
>>>
>>> I just see too many downsides to this and no real upside - other than
>>> not wanting to ensure you've enabled interrupts after disabling them.
>>>
>>> But then I almost never disable interrupts, even in kernel code (and
>>> never in application code).  It's just so rarely necessary.  If you find
>>> you are doing so regularly, you need to be looking at why.
>>>
>>
>> You don't do the same sort of programming as me - just because an idea
>> does not seem useful to /you/, does not mean it is not useful to others.
>>
> 
> I wouldn't say that.  I have worked on some pretty small chips - ones
> that can't even be programmed in C - you have to use assembler.
> 
> And I still don't see a reason for the idea, when there are already good
> ways to do it.
> 
> And obviously the chip manufacturers agree, because *none* of them have
> implemented it.  If someone thought it was a good idea, it would be part
> of their instruction set.

As I have said, I don't know if it is worth the effort implementing such
a feature - it would be nice to have, but it is certainly not essential.
 Chip designers make their decisions based on design costs (instruction
code space, and the effort needed to get it right), implementation costs
(die space, power usage, etc.), and potential usage.  People making
wish-lists of features they would like have different criteria - "nice
to have" weighs very highly.

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


#92984

Fromalready5chosen@yahoo.com
Date2016-08-31 03:57 -0700
Message-ID<72e814e3-42e2-45d7-aac4-426b8b5aef29@googlegroups.com>
In reply to#92982
On Wednesday, August 31, 2016 at 1:39:22 PM UTC+3, David Brown wrote:
> 
> Yes, but in most cases (Alpha, PPC, MIPS, ARM - and probably many others
> that I don't know) this is using a load-link or load-reserve and
> conditional store mechanism.  There is no atomic operation for counter
> incrementing - they have no mechanism for a single read-modify-write
> operation.  Rather, you use the LL and SC instructions to make a
> sequence of operations atomic.  And since the final SC can fail, you
> need a conditional loop.
>

In case of ARM I'd say "this was" instead of "this is".
ARMv8.1 includes several variants of Compare&swap and Fetch-and-modify.

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


#92985

FromDavid Brown <david.brown@hesbynett.no>
Date2016-08-31 15:34 +0200
Message-ID<nq6md7$8mu$1@dont-email.me>
In reply to#92984
On 31/08/16 12:57, already5chosen@yahoo.com wrote:
> On Wednesday, August 31, 2016 at 1:39:22 PM UTC+3, David Brown wrote:
>>
>> Yes, but in most cases (Alpha, PPC, MIPS, ARM - and probably many others
>> that I don't know) this is using a load-link or load-reserve and
>> conditional store mechanism.  There is no atomic operation for counter
>> incrementing - they have no mechanism for a single read-modify-write
>> operation.  Rather, you use the LL and SC instructions to make a
>> sequence of operations atomic.  And since the final SC can fail, you
>> need a conditional loop.
>>
> 
> In case of ARM I'd say "this was" instead of "this is".
> ARMv8.1 includes several variants of Compare&swap and Fetch-and-modify.
> 

My understanding is that the compare-and-exchange instructions on ARM
are deprecated, and the LL/SC instructions are preferred.  But I haven't
kept up with the details here, certainly not on the ARMv8.

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


#92988

Fromalready5chosen@yahoo.com
Date2016-08-31 07:33 -0700
Message-ID<4722129b-297f-4843-9b40-68b1a49e21d1@googlegroups.com>
In reply to#92985
On Wednesday, August 31, 2016 at 4:34:41 PM UTC+3, David Brown wrote:
> On 31/08/16 12:57, already5chosen@yahoo.com wrote:
> > On Wednesday, August 31, 2016 at 1:39:22 PM UTC+3, David Brown wrote:
> >>
> >> Yes, but in most cases (Alpha, PPC, MIPS, ARM - and probably many others
> >> that I don't know) this is using a load-link or load-reserve and
> >> conditional store mechanism.  There is no atomic operation for counter
> >> incrementing - they have no mechanism for a single read-modify-write
> >> operation.  Rather, you use the LL and SC instructions to make a
> >> sequence of operations atomic.  And since the final SC can fail, you
> >> need a conditional loop.
> >>
> > 
> > In case of ARM I'd say "this was" instead of "this is".
> > ARMv8.1 includes several variants of Compare&swap and Fetch-and-modify.
> > 
> 
> My understanding is that the compare-and-exchange instructions on ARM
> are deprecated, and the LL/SC instructions are preferred.  But I haven't
> kept up with the details here, certainly not on the ARMv8.

CISC-style atomic instructions are brand new in ARMv8.1.
I was unaware of previous attempts. ARM ISA history is long and very twisted so I am not ashamed for missing them.
BTW, according to my understanding, old ARM synchronization instructions were of simple exchange variety rather than of compare-and-exchange.

I googled a little deeper and found out that it's not just ARM.
IBM also added to POWER ISA v3.0 an extension that they call Atomic Memory Operations (AMO). The extension includes following instructions:
Fetch and Add
Fetch and XOR
Fetch and OR
Fetch and AND
Fetch and Maximum Unsigned
Fetch and Maximum Signed
Fetch and Maximum Unsigned
Fetch and Minimum Signed
Swap
Compare and Swap Not Equal
Fetch and Increment Bounded
Fetch and Increment Equal
Fetch and Decrement Bounded

It seems, the fashion of 2010s is much close to 1960s than to 1980s.





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


Page 12 of 18 — ← Prev page 1 … 10 11 [12] 13 14 … 18  Next page →

Back to top | Article view | comp.lang.c


csiph-web