Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #92512 > unrolled thread
| Started by | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| First post | 2016-08-19 14:22 -0700 |
| Last post | 2016-08-22 05:11 -0700 |
| Articles | 20 on this page of 355 — 30 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | "Chris M. Thomasson" <invalid@invalid.invalid> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2016-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