Author Topic: Disabling Compiler Optimization vs Using volatile  (Read 27030 times)

0 Members and 14 Guests are viewing this topic.

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Disabling Compiler Optimization vs Using volatile
« on: June 24, 2025, 03:42:57 pm »
I want to set up a timer interrupt on the 8051, using keil ,I’m trying to understand the proper use of the volatile keyword in embedded C. From what I’ve read, if we declare a variable as volatile, we’re basically telling to the compiler that its value might change unexpectedly for example, due to an interrupt or hardware so the compiler should not optimize it by caching the value in a register. Instead, it should always read it from the actual memory location.

Is that the main purpose of using volatile?  if we already know that compiler optimizations can cause issues in such cases, then why don’t we just turn off optimization entirely during compilation? Wouldn’t that avoid the problem?
 

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 638
  • Country: be
Re: Disabling Compiler Optimization vs Using volatile
« Reply #1 on: June 24, 2025, 04:03:02 pm »
Is that the main purpose of using volatile?

Yes


if we already know that compiler optimizations can cause issues in such cases, then why don’t we just turn off optimization entirely during compilation?

What issues? In what cases?

Optimisation has nothing to do with volatile. If you declare a variable volatile, and have two consecutive reads (for example), the compiler must generate code to execute two consecutive reads. Otherwise, it is broken.


Wouldn’t that avoid the problem?

What problem?
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1985
  • Country: 00
Re: Disabling Compiler Optimization vs Using volatile
« Reply #2 on: June 24, 2025, 04:08:55 pm »
Your understanding of volatile sounds correct.

Do mind that race conditions can still occur even when a variable is volatile, as there are some instructions between reading from the volatile memory location and then processing that value. It depends what you're doing if this is going to be a problem.

If you turn off optimization in the compiler, your program may run very slow or become very large. On my ARM projects the difference between -O0 of -O2 in GCC can literally shrink a C++ project from >30kB down to 5kB FLASH with an appropriate runtime speed up as well.

Its generally an indicator of poor code if it changes behavior when the optimizer is turned on (or off). The job of a good compiler is to avoid having to manually write optimized assembly to achieve the goals your program needs to achieve.

Note that again for race conditions, having slow code enlarges the time window (probability) at which these can occur, so its not the case that optimized or unoptimized code will contain less bugs. They contain the same amount of bugs, they simply show in different ways.
 

Online gf

  • Super Contributor
  • ***
  • Posts: 1832
  • Country: de
Re: Disabling Compiler Optimization vs Using volatile
« Reply #3 on: June 24, 2025, 05:39:58 pm »
if we already know that compiler optimizations can cause issues in such cases, then why don’t we just turn off optimization entirely during compilation?

The guarantees and semantics of the C standard are independent of optimization. The standard does not offer additional guarantees or special semantics for non-optimized code.
 
The following users thanked this post: langwadt, Siwastaja, newbrain, abeyer

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11291
  • Country: fi
Re: Disabling Compiler Optimization vs Using volatile
« Reply #4 on: June 24, 2025, 05:48:50 pm »
if we already know that compiler optimizations can cause issues in such cases, then why don’t we just turn off optimization entirely during compilation?

The guarantees and semantics of the C standard are independent of optimization. The standard does not offer additional guarantees or special semantics for non-optimized code.

This, this and this. The usual explanation that volatile somehow "bypasses optimization" is trying to be helpful, but really isn't. It's an unnecessarily deep compiler-internal detail, which is better left not mentioned, than oversimplified.

C language is, since late 1980's, a high-level abstract programming language defined upon the terms of observable behavior of the C abstract machine. The whole concept of high-level languages is that programmer writes a formal description (computer program in high-level language) about what result the program is supposed to produce, and the compiler turns it into machine code, trying to do as good job as possible. Doing "good job" can be also called optimizing, but it really isn't some separate process.

In other words, even if you try to disable all optimizations by modifying compiler parameters, it is still possible that broken code is still broken. Fix: write correct code. That means, using volatile qualifier if it is possible that variable will be modified outside of the usual code flow, or if you need to generate load and store instructions for every access, like you might do with peripheral registers.

Besides, optimizations are very necessary. Performance and size are both pretty important. A large number of real-world MCU projects will just become too big that they do not fit in flash memory, or too slow they can't satisfy the timing needs, if you try to compile them with something like -O0 (on GCC).

So by disabling optimizations, you can't guarantee broken code starts to work reliably (it might by luck), but on the other hand, you sacrifice a lot of performance. This is why it is usually a good idea to optimize either at -Os or -O2 (or even -O3).

Some people find that changing optimization settings is a good way to fight bugs, but I disagree. It is too coarse to even find bugs. And if lower optimization setting successfully hides a bug, then what? You still need to find it - develop good bughunting strategies instead, you will need them.

And indeed, volatile only guarantees memory accesses will be generated instead of "caching" (a very loose term) within the compiler. If you need atomicity, then that's a completely separate subject.
« Last Edit: June 24, 2025, 05:58:11 pm by Siwastaja »
 
The following users thanked this post: newbrain, Doctorandus_P, AndersJ, abeyer

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4660
  • Country: us
Re: Disabling Compiler Optimization vs Using volatile
« Reply #5 on: June 24, 2025, 09:32:22 pm »
Quote
if we already know that compiler optimizations can cause issues in such cases, then why don’t we just turn off optimization entirely during compilation? Wouldn’t that avoid the problem?   
Why would that ever be a preferred solution?  "volatile" is correct and more efficient overall.
Turning off optimization is likely to be particularly costly on the less-C-friendly architectures like PIC16 and 8051.

Also, "no optimization" is likely to be ambiguous and compiler dependent, and I don't think you can count on it resulting in the desired behavior for shared ("volatile") variables. gcc's "-O0" spits out really awful code and will indeed always load variables from "memory."  I don't know what Keil does...

 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
Re: Disabling Compiler Optimization vs Using volatile
« Reply #6 on: June 25, 2025, 01:41:29 am »
So by disabling optimizations, you can't guarantee broken code starts to work reliably (it might by luck), but on the other hand, you sacrifice a lot of performance. This is why it is usually a good idea to optimize either at -Os or -O2 (or even -O3).

I usually find very little additional benefit in size or speed from anything more than -O aka -O1 on my own code.

I don't like the general code size expansion of -O3 so if I'm tempted by that I'll either isolate it to specific functions, or hand-code those functions.

Never, ever, use -O0 (aka no -O at all). You might as well code in Python. Well, ok ... JavaScript.
 
The following users thanked this post: Siwastaja

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #7 on: June 25, 2025, 09:08:16 am »
Prediction: the OP will never reply.

Why? They have made 4 posts, all thread starters.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: hans, tooki

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11291
  • Country: fi
Re: Disabling Compiler Optimization vs Using volatile
« Reply #8 on: June 25, 2025, 10:33:14 am »
Prediction: the OP will never reply.

Why? They have made 4 posts, all thread starters.

Normal Indian AI training bot. To reply, or not to reply, that's an interesting question. I get a feeling feeding incorrect data to it on purpose would be funny; then again, good replies serve all the others on this forum.

I try to avoid answering to very specific questions of these bots, but for something of universal value to others, I do reply.
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: Disabling Compiler Optimization vs Using volatile
« Reply #9 on: June 25, 2025, 12:55:28 pm »
Prediction: the OP will never reply.


Your prediction is wrong I’m right here.

Just because I started a two threads doesn’t mean I won’t follow up. I genuinely appreciate the help and I’m actively learning. Also, please try to keep the discussion on-topic it really helps those of us who are here to learn

I don’t want to write code without understanding the basics. I’ve seen many people just copy-paste code without really knowing what it does  and honestly, I don’t like that approach. I’ve decided to read the datasheet carefully, write the code myself. That’s how I believe real learning happens.

Right now, I’m working on setting up a 1ms timer interrupt using the AT89S52 microcontroller. I’m using the Keil compiler along with an Atmel programmer. I’ve been going through the datasheet and studying all three timers to figure out which one would be the best fit  but that’s a separate topic.

The reason I’m asking about the volatile keyword is because it’s often used when sharing variables between the main program and the ISR.

back to topic when we say that the value of a variable can change at any time from outside the program, what exactly does that mean?

Does it mean that the  program itself won’t change the value, but external factors like an interrupt or hardware peripheral might update it?
« Last Edit: June 25, 2025, 01:00:50 pm by EVblog1 »
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #10 on: June 25, 2025, 02:05:20 pm »
Prediction: the OP will never reply.


Your prediction is wrong I’m right here.

Just because I started a two threads doesn’t mean I won’t follow up.

Four threads at the time of writing.

Your single followup was after it was noted you hadn't followed up to any of your four threads.



BTW,"volatile" is a frequently misunderstood qualifier; it is not simply and easily understood in a few words.
BTW C is full of surprising "implementation defined" and "undefined" behaviour that catches out even experienced users.

As an example of that realise that people had to be forced to realise that in C/C++ "Threads cannot be implemented as a library" https://web.archive.org/web/20230821125225/https://www.hpl.hp.com/techreports/2004/HPL-2004-209.pdf The resolution of that took a decade(!) and required the introduction of the C memory model (the necessity for that C had studiously tried to ignore for >30 years!).

So, if you want to have a multithreaded system (e.g. several threads and/or interrupts) you need to either understand the memory model, or use a threading library, or go outside the C specification.

Perhaps that will prompt you to realise why alternatives to C are becoming more popular.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: EVblog1

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 638
  • Country: be
Re: Disabling Compiler Optimization vs Using volatile
« Reply #11 on: June 25, 2025, 03:00:47 pm »
back to topic when we say that the value of a variable can change at any time from outside the program, what exactly does that mean?

Does it mean that the  program itself won’t change the value, but external factors like an interrupt or hardware peripheral might update it?

Yes. Consider PSW register in 8051 realm. Parity flag indicates even/odd number of ones in the accumulator -- which may or may not change on every command that involves accumulator, completely independently of your program's flow.
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11291
  • Country: fi
Re: Disabling Compiler Optimization vs Using volatile
« Reply #12 on: June 25, 2025, 03:26:20 pm »
back to topic when we say that the value of a variable can change at any time from outside the program, what exactly does that mean?

Does it mean that the  program itself won’t change the value, but external factors like an interrupt or hardware peripheral might update it?

Yes, external factors like another thread (in multi-threaded programming) writing to that variable, DMA controller, another CPU core, hardware peripheral writing to it.

Typical example would be memory-mapped peripheral register. Like GPIO input register, which autonomously changes its value all the time based on the voltage of the pin. You most likely want to read the current value every time you access it in C code. Therefore, these input registers are qualified volatile in the header files supplied by the manufacturer.

But also: code where the CPU jumps to autonomously, like interrupt handler (common on microcontrollers, or if writing operating system kernel), or signal handler (if writing userland programs on operating systems; function that is automagically called when user hits CTRL+C in Unix would be typical example). Code flow that isn't visible to the compiler.

If you e.g. call a function between accesses to a global variable, compiler will figure out if the variable might be modified in the function, and if unable to do so, assumes it might be modified - no problem, compilers are very good at this and compiler bugs are extremely rare. But if interrupt controller moves the execution to a function, compiler cannot have any idea when that might happen or might not. Therefore, for variables set in interrupt handlers, you may want to qualify them as volatile if you want the effect to be visible to rest of the program. You can of course leave the volatile qualifier out at your own risk if you know what you are doing, or inspect the compiler output yourself.
 
The following users thanked this post: EVblog1

Offline HwAoRrDk

  • Super Contributor
  • ***
  • Posts: 1931
  • Country: gb
Re: Disabling Compiler Optimization vs Using volatile
« Reply #13 on: June 25, 2025, 04:12:29 pm »
It should probably be mentioned as part of this discussion of volatile variables that making a variable volatile does not also solve the problem of atomicity.

Atomicity can be a concern when working with 8-bit microcontrollers, as you're frequently dealing with variables bigger than 8 bits - e.g. 16-bit, 32-bit integers, etc.

The problem is probably best illustrated with an example:

Say you have a global 32-bit integer variable foo. That variable is set within an interrupt service routine, and read by and used in some calculation by other code in the main loop. You have it declared as volatile, so the compiler won't make any assumptions about its value, and when reading it in the main loop will always read from the relevant memory location every time. But! Your CPU is only 8 bits, so it takes at least 4 instructions to read each byte of the variable's value into registers and work on it (assuming it even has that many registers and doesn't have to expend even more instructions playing musical chairs). That means the CPU is not reading the variable's value atomically (i.e. all in one go), and there is potential for the IRQ to interrupt half-way through reading the variable's value and change it.

That potential sequence of events could go like:

1. Value of foo = 0xAABBCCDD
2. CPU loads byte 0 (0xAA) into a register
3. CPU loads byte 1 (0xBB) into a register
**** IRQ, jump to ISR ****
4. ISR sets foo = 0xCAFEDEAD
**** ISR returns ****
5. CPU loads byte 2 (0xDE) into a register
6. CPU loads byte 3 (0xAD) into a register
7. CPU sees value of the variable as 0xAABBDEAD, not 0xAABBCCDD or 0xCAFEDEAD!

The solution is, when reading the variable any time outside an ISR, to globally disable interrupts (or, at least, the relevant individual IRQ), take a copy of the variable, then re-enable interrupts, and work on the copy.

When you're working with 32-bit MCUs, this class of problem tends to go away, as you're infrequently working with variables larger than the CPU's native word size (32 bits), which it can typically work with atomically.
« Last Edit: June 25, 2025, 04:15:32 pm by HwAoRrDk »
 
The following users thanked this post: Siwastaja, tooki

Offline Tation

  • Frequent Contributor
  • **
  • Posts: 311
  • Country: pt
Re: Disabling Compiler Optimization vs Using volatile
« Reply #14 on: June 25, 2025, 05:59:44 pm »
When you are working with 32-bit MCUs, this class of problem tends to go away, as you're infrequently working with variables larger than the CPU's native word size (32 bits), which it can typically work with atomically.

With 32 bit (or any other size) processor you still have a problem if you want to read a variable, modify it and write it back. If such read-modify-write sequence is not performed atomically, any ISR, thread or core can interrupt the sequence, access the variable and make a mess.

volatile will not solve this, neither playing with compiler CLI options. Disabling interrupts can help preventing ISR or other threads from breaking havoc, but will not protect from other cores accessing the variable. For this you need hardware support to ensure that the RMW operation executes atomically, or to know that somebody attempted to access or accessed the variable during it (ARM's LDREX/STREX instructions, LR/SC and AMO instruction in RISC-V,...).

Look for LL/SC, if wanting more.
 
The following users thanked this post: hans

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #15 on: June 25, 2025, 06:38:59 pm »
When you are working with 32-bit MCUs, this class of problem tends to go away, as you're infrequently working with variables larger than the CPU's native word size (32 bits), which it can typically work with atomically.

With 32 bit (or any other size) processor you still have a problem if you want to read a variable, modify it and write it back. If such read-modify-write sequence is not performed atomically, any ISR, thread or core can interrupt the sequence, access the variable and make a mess.

volatile will not solve this, neither playing with compiler CLI options. Disabling interrupts can help preventing ISR or other threads from breaking havoc, but will not protect from other cores accessing the variable. For this you need hardware support to ensure that the RMW operation executes atomically, or to know that somebody attempted to access or accessed the variable during it (ARM's LDREX/STREX instructions, LR/SC and AMO instruction in RISC-V,...).

Look for LL/SC, if wanting more.

That is indeed one of the problems pointed out in Hans Boehm's paper "Threads cannot be implemented as a library".

When I started using C in the early 80s, the two (and only two) books on C were explicit that multithreading was outside the scope of the language. That seemed to be wished away by practitioners of all degrees of competence. They relied on code libraries that were compiler and machine specific, and could not be expressed in C.

10 years later (in 1994/6) Java addressed the issue explicitly, and hence became the language of choice for new heavily multithreaded applications. Just as well since multicore processors were becoming commonplace.

For another 10 years C had its head in the sand, being more concerned with whether "casting away constness" was obligatory or forbidden. Finally, in 2004 Boehm felt it necessary to "remind" people about that multithreading hole. Boehm also pointed out what was necessary: a memory model.

Eventually, after yet another 10 years had passed, C finally gained a memory model - 20 years after Java had nailed the issue.

And C people claim they are the most knowledgeable wizards around!
« Last Edit: June 25, 2025, 06:41:00 pm by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4660
  • Country: us
Re: Disabling Compiler Optimization vs Using volatile
« Reply #16 on: June 26, 2025, 05:12:08 am »
Quote
[multi-threading] relied on code libraries that were compiler and machine specific, and could not be expressed in C.
So what?
Why is it such a big deal to require a small core of machine-specific assembly language to implement some feature?

Back in the old days, we took it for granted that there were things that could not be done within the limits of the "preferred" language.  Sometimes your fortran program had to have code written in assembly language, or your BASIC program had to POKE some hex code into memory and then CALL it.  It was no big deal...
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 11291
  • Country: fi
Re: Disabling Compiler Optimization vs Using volatile
« Reply #17 on: June 26, 2025, 06:50:40 am »
tggzzz's posts are perfect example of the discrepancy between theory, and the real world.

In real world, no one is using Java for "new heavily multi-threaded applications" anymore (if they ever did) and Java is notorious for its poor performance. In the past at university, for half a year, I had to try to maintain a server project written in Java which did absolutely trivial amount of processing (like hundreds of bytes per second from a handful of connections!) and was not only leaking memory (like Java applications so often do), but also leaking threads, and we had a supervisor process which killed and restarted the whole thing when thread count exceeded 200. The whole thing was written in Best Java Practices (problemFactoryBeanFactory etc.), and was completely unmaintainable.

Of course, the whole thing would have been obvious in single-threaded C application using select() or something similar, and fewer lines of code total, than the file count of the Java project.

Most people are very happy to see Java disappear. Like communism, it had many really good ideas, but did not work in practice, for whatever reasons that would be interesting to analyze but outside the scope of this discussion, because, like many wise men say, practice trumps theory any day. Meanwhile, C might be inelegant and "threads cannot be implemented as a library and constness should not be cast away" or whatever, but in real world C is used A LOT for performance critical multithreaded applications, and threads are implemented as libraries all the time and people seem to deal with this just fine, except those who do not actually write these programs but instead only talk about them on internet forums.
« Last Edit: June 26, 2025, 06:55:16 am by Siwastaja »
 
The following users thanked this post: mikerj, JPortici, gerbay

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
Re: Disabling Compiler Optimization vs Using volatile
« Reply #18 on: June 26, 2025, 09:15:28 am »
Quote
[multi-threading] relied on code libraries that were compiler and machine specific, and could not be expressed in C.
So what?
Why is it such a big deal to require a small core of machine-specific assembly language to implement some feature?

The big deal is getting people to accept that a few instructions of asm are needed, not the difficulty of writing them.

It's on the same level as "a C program can't set up its own stack". And, in fact, you hit exactly the same thing as part of thread creation too -- you can *almost* do a cooperative threading library in portable C, using setjmp/longjmp, but not quite. You need to know where in the jmp_buf the stack pointer is stored, and overwrite it. The PC too. "Volatile" handles the rest.

Preemptive threads needs a bit more, including a way to do critical sections, but mostly that they have to save and restore ALL registers and some other state, not just the ones preserved by function call/return.

Also, when I did this on Windows I had to write my own entire setjmp & longjmp because the standard one had a whole lot of extra SEH bollocks that also needed patching (or ignoring) for new threads.
« Last Edit: June 26, 2025, 09:17:39 am by brucehoult »
 

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 2254
  • Country: ua
Re: Disabling Compiler Optimization vs Using volatile
« Reply #19 on: June 26, 2025, 09:24:22 am »
This is interesting.

I had a case where I had to disable compiler optimizations for parts of the code using gcc-specific inline instructions to prevent the compiler from optimizing out the "write-then-read" sequence (or double reads, I don't remember it clearly now) when accessing memory directly in a GPIO pin bitbanging scenario.

Apparently the canonical way of solving it would be to use the volatile modifier. Live and learn. I will need to check it if I ever touch that code again.
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #20 on: June 26, 2025, 09:30:15 am »
Quote
[multi-threading] relied on code libraries that were compiler and machine specific, and could not be expressed in C.
So what?
Why is it such a big deal to require a small core of machine-specific assembly language to implement some feature?

Back in the old days, we took it for granted that there were things that could not be done within the limits of the "preferred" language.  Sometimes your fortran program had to have code written in assembly language, or your BASIC program had to POKE some hex code into memory and then CALL it.  It was no big deal...

All that is very true, and is exactly what we did.

Only after 30 years of sweeping the problems under the carpet did the C standards finally evolve to the point at which that was no longer necessary.

C is a very complicated language, with many nooks and crannies. Hence of necessity beginners are taught (often badly!) about small parts of C. They then begin to expand from that small core onto "advanced" topics like volatile etc - and generate code which seems to work but has many subtle unrepeatable problems.

If you have a good way of quickly forcing beginners to realise the inadequacy of the bits of C they have been taught, I'd like to know. Shockingly IMNSHO Hans Boehm had to force experts[1] into understanding that.

[1] nominal and/or self-proclaimed experts on the various committees
« Last Edit: June 26, 2025, 09:42:32 am by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: hans

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #21 on: June 26, 2025, 09:38:56 am »
tggzzz's posts are perfect example of the discrepancy between theory, and the real world.

In real world, no one is using Java for "new heavily multi-threaded applications" anymore (if they ever did) and Java is notorious for its poor performance.

You are joking, aren't you?!

You can only make that assertion by ignoring telecom systems and enterprise systems.

Quote
In the past at university, for half a year, I had to try to maintain a server project written in Java which did absolutely trivial amount of processing (like hundreds of bytes per second from a handful of connections!) and was not only leaking memory (like Java applications so often do), but also leaking threads, and we had a supervisor process which killed and restarted the whole thing when thread count exceeded 200. The whole thing was written in Best Java Practices (problemFactoryBeanFactory etc.), and was completely unmaintainable.

A university project written by students that wasn't up to the job? Who would have thought it.

Fortunately every C/C++ university project works perfectly and is not based on anti-patterns. Perish the thought.

Quote
Of course, the whole thing would have been obvious in single-threaded C application using select() or something similar, and fewer lines of code total, than the file count of the Java project.

Most people are very happy to see Java disappear. Like communism, it had many really good ideas, but did not work in practice, for whatever reasons that would be interesting to analyze but outside the scope of this discussion, because, like many wise men say, practice trumps theory any day. Meanwhile, C might be inelegant and "threads cannot be implemented as a library and constness should not be cast away" or whatever, but in real world C is used A LOT for performance critical multithreaded applications, and threads are implemented as libraries all the time and people seem to deal with this just fine, except those who do not actually write these programs but instead only talk about them on internet forums.

I have written many such applications over the decades. Of particular relevance is that one of my soft realtime Java telecoms applications blew the equivalent C/C++ application out of the water in terms of performance.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: hans

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Disabling Compiler Optimization vs Using volatile
« Reply #22 on: June 26, 2025, 09:41:06 am »
Quote
[multi-threading] relied on code libraries that were compiler and machine specific, and could not be expressed in C.
So what?
Why is it such a big deal to require a small core of machine-specific assembly language to implement some feature?

The big deal is getting people to accept that a few instructions of asm are needed, not the difficulty of writing them.

It's on the same level as "a C program can't set up its own stack". And, in fact, you hit exactly the same thing as part of thread creation too -- you can *almost* do a cooperative threading library in portable C, using setjmp/longjmp, but not quite. You need to know where in the jmp_buf the stack pointer is stored, and overwrite it. The PC too. "Volatile" handles the rest.

Preemptive threads needs a bit more, including a way to do critical sections, but mostly that they have to save and restore ALL registers and some other state, not just the ones preserved by function call/return.

Also, when I did this on Windows I had to write my own entire setjmp & longjmp because the standard one had a whole lot of extra SEH bollocks that also needed patching (or ignoring) for new threads.

Precisely :)

There is too much of the attitude that "C is both necessary and sufficient". Neither is true.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: hans

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 2254
  • Country: ua
Re: Disabling Compiler Optimization vs Using volatile
« Reply #23 on: June 26, 2025, 10:07:19 am »
C is a very complicated language
No. It is as simple as it gets (besides assembler and machine code). It allows you to tell the computer what you want it to do in very simple terms, and it does precisely that. It allows the programmer to understand what he is doing, but it also requires the programmer to understand what he is doing. C is almost perfect, but only for those who can express their thoughts and goals clearly and coherently. Not all people can do it, so other languages have become a necessity.

edit: crossed out a logically incorrect conclusion.
« Last Edit: June 26, 2025, 10:37:46 am by shapirus »
 
The following users thanked this post: mikerj

Offline SteveThackery

  • Super Contributor
  • ***
  • Posts: 3397
  • Country: gb
  • 50 year novice
Re: Disabling Compiler Optimization vs Using volatile
« Reply #24 on: June 26, 2025, 10:24:05 am »
Isn't FreeRTOS written in C? Does that count as a library?
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->