Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2021-11

Optimisation and thread safety

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

J. Gareth Moreton

Hi everyone,

I have a question when it comes to optimising memory reads and writes.  What are the rules for FPC when it comes to writing to memory and then reading from it later within a single subroutine? For example, say I had this pair of commands:

    movq    %rdx,-584(%rbp)
    movl    -584(%rbp),%eax

That could easily be converted to "movl %edx,%eax", especially as %rbp is likely pointing to the top of the stack.  But if the reference uses different registers, would it still be safe to make this optimisation given that the scheduler could suspend the thread in between the two instructions and then another thread writes to the same memory block before control is returned?

I am aware of other examples that require caution.  For example:

    movslq    -608(%rbp),%rdx
    subl    %eax,-84(%rbp,%rdx,4)
    movslq    -608(%rbp),%rdx

Here it might be tempting to remove the second "movslq" instruction, but the value of %rdx could happen to be equal to -131, which would allow the subl instruction to modify -608(%rbp), and in this situation, it's quite likely if a malicious input is given to the program to manipulate the value stored at -608(%rbp) and invoke a buffer overrun.

So in conclusion, theoretically, where is it perfectly safe to assume the value in memory hasn't changed, where would it be permissible only under -O4 and where must it not be optimised at all?

Gareth aka. Kit

P.S. Assembly examples were taken from the System unit.

This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Michael Van Canneyt
to J. Gareth Moreton
J. Gareth Moreton wrote 16 lines
Hi everyone, I have a question when it comes to optimising memory reads and writes.  What are the rules for FPC when it comes to writing to memory and then reading from it later within a single subroutine? For example, say I had this pair of commands:     movq    %rdx,-584(%rbp)     movl    -584(%rbp),%eax That could easily be converted to "movl %edx,%eax", especially as %rbp is likely pointing to the top of the stack.  But if the reference uses different registers, would it still be safe to make this optimisation given that the scheduler could suspend the thread in between the two instructions and then another thread writes to the same memory block before control is returned?

The user is responsible for synchronizing between threads, so I don't think the compiler needs to take this into account ?

Michael.

Reply by email

Florian Klämpfl
to J. Gareth Moreton: I have a question when it comes to optimising memory reads and writes.  What are the…
Show quoted text 10 lines
Am 13.11.2021 um 00:55 schrieb J. Gareth Moreton via fpc-devel : Hi everyone, I have a question when it comes to optimising memory reads and writes. What are the rules for FPC when it comes to writing to memory and then reading from it later within a single subroutine? For example, say I had this pair of commands: movq %rdx,-584(%rbp) movl -584(%rbp),%eax That could easily be converted to "movl %edx,%eax", especially as %rbp is likely pointing to the top of the stack.

This is not possible as rsp could be used as normal register.

If the reference is not marked as being read volatile, you can change the second mov into movl %edx,%ea.

For further optimizations you have to track tai_tempalloc which we don’t yet.

Show quoted text 9 lines
But if the reference uses different registers, would it still be safe to make this optimisation given that the scheduler could suspend the thread in between the two instructions and then another thread writes to the same memory block before control is returned? I am aware of other examples that require caution. For example: movslq -608(%rbp),%rdx subl %eax,-84(%rbp,%rdx,4) movslq -608(%rbp),%rdx Here it might be tempting to remove the second "movslq" instruction, but the value of %rdx could happen to be equal to -131, which would allow the subl instruction to modify -608(%rbp), and in this situation, it's quite likely if a malicious input is given to the program to manipulate the value stored at -608(%rbp) and invoke a buffer overrun.

It could be also a pointer aliasing the memory location or an array, so this is not safe in any case. So something like a[a[1234]] which might be valid code imo.

Show quoted text 15 lines
So in conclusion, theoretically, where is it perfectly safe to assume the value in memory hasn't changed, where would it be permissible only under -O4 and where must it not be optimised at all? Gareth aka. Kit P.S. Assembly examples were taken from the System unit. -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

J. Gareth Moreton
to Florian Klämpfl

I figured that if you read from memory, and then write to memory, it's not safe to read from the same memory block again because the write address could be equal to (or overlap) the read memory and it's impossible to rule that out if different registers are used. It might be okay if the references use the same registers (and remain constant) and only the offsets differ (and, again, there's no overlap), but otherwise it would only be safe when using %rsp, since I'm pretty sure the compiler does not use that for anything other than the stack pointer.

If it's the programmer's job to handle thread synchronisation, that alleviates some pressure.

Thanks for the insight, Florian and Michael.

Gareth aka. Kit

Florian Klämpfl wrote 46 lines
> Am 13.11.2021 um 00:55 schrieb J. Gareth Moreton via fpc-devel : > > Hi everyone, > > I have a question when it comes to optimising memory reads and writes. What are the rules for FPC when it comes to writing to memory and then reading from it later within a single subroutine? For example, say I had this pair of commands: > > movq %rdx,-584(%rbp) > movl -584(%rbp),%eax > > That could easily be converted to "movl %edx,%eax", especially as %rbp is likely pointing to the top of the stack. This is not possible as rsp could be used as normal register. If the reference is not marked as being read volatile, you can change the second mov into movl %edx,%ea. For further optimizations you have to track tai_tempalloc which we don’t yet. > But if the reference uses different registers, would it still be safe to make this optimisation given that the scheduler could suspend the thread in between the two instructions and then another thread writes to the same memory block before control is returned? > > I am aware of other examples that require caution. For example: > > movslq -608(%rbp),%rdx > subl %eax,-84(%rbp,%rdx,4) > movslq -608(%rbp),%rdx > > Here it might be tempting to remove the second "movslq" instruction, but the value of %rdx could happen to be equal to -131, which would allow the subl instruction to modify -608(%rbp), and in this situation, it's quite likely if a malicious input is given to the program to manipulate the value stored at -608(%rbp) and invoke a buffer overrun. It could be also a pointer aliasing the memory location or an array, so this is not safe in any case. So something like a[a[1234]] which might be valid code imo. > So in conclusion, theoretically, where is it perfectly safe to assume the value in memory hasn't changed, where would it be permissible only under -O4 and where must it not be optimised at all? > > Gareth aka. Kit > > P.S. Assembly examples were taken from the System unit. > > > -- > This email has been checked for viruses by Avast antivirus software. > https://www.avast.com/antivirus > > _______________________________________________ > fpc-devel maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email